Spring Boot Admin是一個開源社區項目,用於管理和監控SpringBoot應用程序。 應用程序做爲Spring Boot Admin Client向爲Spring Boot Admin Server註冊(經過HTTP)或使用SpringCloud註冊中心(例如Eureka,Consul)發現。 UI是的Vue.js應用程序,展現Spring Boot Admin Client的Actuator端點上的一些監控。服務端採用Spring WebFlux + Netty的方式。Spring Boot Admin爲註冊的應用程序提供如下功能:java
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.gf</groupId> <artifactId>admin-server</artifactId> <version>0.0.1-SNAPSHOT</version> <name>admin-server</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-boot-admin.version>2.1.0</spring-boot-admin.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-starter-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-dependencies</artifactId> <version>${spring-boot-admin.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
spring: application: name: admin-server server: port: 8769
啓動類加上@EnableAdminServer註解,開啓AdminServer的功能:git
@SpringBootApplication @EnableAdminServer public class AdminServerApplication { public static void main(String[] args) { SpringApplication.run( AdminServerApplication.class, args ); } }
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.gf</groupId> <artifactId>admin-client</artifactId> <version>0.0.1-SNAPSHOT</version> <name>admin-client</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-boot-admin.version>2.1.0</spring-boot-admin.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-starter-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-dependencies</artifactId> <version>${spring-boot-admin.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
spring: application: name: admin-client boot: admin: client: url: http://localhost:8769 server: port: 8768 management: endpoints: web: exposure: include: '*' endpoint: health: show-details: ALWAYS
@SpringBootApplication public class AdminClientApplication { public static void main(String[] args) { SpringApplication.run( AdminClientApplication.class, args ); } }
啓動兩個工程,在瀏覽器上輸入localhost:8769 ,瀏覽器顯示的界面以下:程序員
查看wallboard:github
點擊wallboard,能夠查看admin-client具體的信息,好比內存狀態信息:web
查看spring bean的狀況:redis
查看應用程序運行情況,信息和詳細:spring
還有不少監控信息,多點一點就知道。數據庫
這是一個 eureka-server 註冊中心。apache
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.gf</groupId> <artifactId>sc-admin-server</artifactId> <version>0.0.1-SNAPSHOT</version> <name>sc-admin-server</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-boot-admin.version>2.1.0</spring-boot-admin.version> <spring-cloud.version>Finchley.RELEASE</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-starter-server</artifactId> <version>2.1.0</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <dependency> <groupId>org.jolokia</groupId> <artifactId>jolokia-core</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-dependencies</artifactId> <version>${spring-boot-admin.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
spring: application: name: sc-eureka-server server: port: 8761 eureka: client: service-url: defaultZone: http://localhost:8761/eureka register-with-eureka: false fetch-registry: false management: endpoints: web: exposure: include: "*" endpoint: health: show-details: ALWAYS
@SpringBootApplication @EnableEurekaServer public class ScEurekaServerApplication { public static void main(String[] args) { SpringApplication.run( ScEurekaServerApplication.class, args ); } }
這是一個 Spring Boot Admin Server端。瀏覽器
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.gf</groupId> <artifactId>sc-admin-server</artifactId> <version>0.0.1-SNAPSHOT</version> <name>sc-admin-server</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-boot-admin.version>2.1.0</spring-boot-admin.version> <spring-cloud.version>Finchley.RELEASE</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-starter-server</artifactId> <version>2.1.0</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <dependency> <groupId>org.jolokia</groupId> <artifactId>jolokia-core</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-dependencies</artifactId> <version>${spring-boot-admin.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
spring: application: name: admin-server server: port: 8769 eureka: client: registryFetchIntervalSeconds: 5 service-url: defaultZone: ${EUREKA_SERVICE_URL:http://localhost:8761}/eureka/ instance: leaseRenewalIntervalInSeconds: 10 health-check-url-path: /actuator/health management: endpoints: web: exposure: include: "*" endpoint: health: show-details: ALWAYS
@SpringBootApplication @EnableAdminServer @EnableDiscoveryClient public class ScAdminServerApplication { public static void main(String[] args) { SpringApplication.run( ScAdminServerApplication.class, args ); } }
這是一個 Spring Boot Admin client 端。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.gf</groupId> <artifactId>sc-admin-client</artifactId> <version>0.0.1-SNAPSHOT</version> <name>sc-admin-client</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-boot-admin.version>2.1.0</spring-boot-admin.version> <spring-cloud.version>Finchley.SR2</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-starter-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-dependencies</artifactId> <version>${spring-boot-admin.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
spring: application: name: sc-admin-client eureka: instance: leaseRenewalIntervalInSeconds: 10 health-check-url-path: /actuator/health client: registryFetchIntervalSeconds: 5 service-url: defaultZone: ${EUREKA_SERVICE_URL:http://localhost:8761}/eureka/ management: endpoints: web: exposure: include: "*" endpoint: health: show-details: ALWAYS server: port: 8762
@SpringBootApplication @EnableDiscoveryClient public class ScAdminClientApplication { public static void main(String[] args) { SpringApplication.run( ScAdminClientApplication.class, args ); } }
啓動三個工程,訪問localhost:8769,出現以下界面:
admin 會本身拉取 Eureka 上註冊的 app 信息,主動去註冊。這也是惟一區別以前入門中手動註冊的地方,就是 client 端不須要 admin-client 的依賴,也不須要配置 admin 地址了,一切所有由 admin-server 本身實現。這樣的設計對環境變化很友好,不用改了admin-server後去改全部app 的配置了。
Web應用程序中的身份驗證和受權有多種方法,所以Spring Boot Admin不提供默認方法。默認狀況下,spring-boot-admin-server-ui提供登陸頁面和註銷按鈕。咱們結合 Spring Security 實現須要用戶名和密碼登陸的安全認證。
sc-admin-server工程的pom文件須要增長如下的依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
在 sc-admin-server工的配置文件 application.yml 中配置 spring security 的用戶名和密碼,這時須要在服務註冊時帶上 metadata-map 的信息,以下:
spring: security: user: name: "admin" password: "admin" eureka: instance: metadata-map: user.name: ${spring.security.user.name} user.password: ${spring.security.user.password}
@EnableWebSecurity註解以及WebSecurityConfigurerAdapter一塊兒配合提供基於web的security。繼承了WebSecurityConfigurerAdapter以後,再加上幾行代碼,咱們就能實現要求用戶在進入應用的任何URL以前都進行驗證的功能,寫一個配置類SecuritySecureConfig繼承WebSecurityConfigurerAdapter,配置以下:
@Configuration public class SecuritySecureConfig extends WebSecurityConfigurerAdapter { private final String adminContextPath; public SecuritySecureConfig(AdminServerProperties adminServerProperties) { this.adminContextPath = adminServerProperties.getContextPath(); } @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler(); successHandler.setTargetUrlParameter("redirectTo"); successHandler.setDefaultTargetUrl(adminContextPath + "/"); http.authorizeRequests() //授予對全部靜態資產和登陸頁面的公共訪問權限。 .antMatchers(adminContextPath + "/assets/**").permitAll() .antMatchers(adminContextPath + "/login").permitAll() //必須對每一個其餘請求進行身份驗證 .anyRequest().authenticated() .and() //配置登陸和註銷 .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and() .logout().logoutUrl(adminContextPath + "/logout").and() //啓用HTTP-Basic支持。這是Spring Boot Admin Client註冊所必需的 .httpBasic().and(); // @formatter:on } }
從新訪問 http://localhost:8769/ 會出現登陸界面,密碼是 配置文件中配置好的,帳號 admin 密碼 admin,界面以下:
在 Spring Boot Admin 中 當註冊的應用程序狀態更改成DOWN、UNKNOWN、OFFLINE 均可以指定觸發通知,下面講解配置郵件通知。
在sc-admin-server工程pom文件,加上mail的依賴,以下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency>
在配置文件application.yml文件中,配置收發郵件的配置:
spring: mail: host: smtp.163.com username: xxxx@163.com password: xxxx properties: mail: smtp: auth: true starttls: enable: true required: true boot: admin: notify: mail: from: xxxx@163.com to: xxxx@qq.com
配置後,重啓sc-admin-server工程,以後若出現註冊的客戶端的狀態從 UP 變爲 OFFLINE 或其餘狀態,服務端就會自動將電子郵件發送到上面配置的收件地址。
注意 : 配置了郵件通知後,會出現 反覆通知 service offline / up。這個問題的緣由在於 查詢應用程序的狀態和信息超時,下面給出兩種解決方案:
#方法一:增長超時時間(單位:ms) spring.boot.admin.monitor.read-timeout=20000 #方法二:關閉閉未使用或不重要的檢查點 management.health.db.enabled=false management.health.mail.enabled=false management.health.redis.enabled=false management.health.mongo.enabled=false
能夠經過添加實現Notifier接口的Spring Beans來添加您本身的通知程序,最好經過擴展 AbstractEventNotifier或AbstractStatusChangeNotifier。在sc-admin-server工程中編寫一個自定義的通知器:
@Component public class CustomNotifier extends AbstractStatusChangeNotifier { private static final Logger LOGGER = LoggerFactory.getLogger( LoggingNotifier.class); public CustomNotifier(InstanceRepository repository) { super(repository); } @Override protected Mono<Void> doNotify(InstanceEvent event, Instance instance) { return Mono.fromRunnable(() -> { if (event instanceof InstanceStatusChangedEvent) { LOGGER.info("Instance {} ({}) is {}", instance.getRegistration().getName(), event.getInstance(), ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus()); String status = ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus(); switch (status) { // 健康檢查沒經過 case "DOWN": System.out.println("發送 健康檢查沒經過 的通知!"); break; // 服務離線 case "OFFLINE": System.out.println("發送 服務離線 的通知!"); break; //服務上線 case "UP": System.out.println("發送 服務上線 的通知!"); break; // 服務未知異常 case "UNKNOWN": System.out.println("發送 服務未知異常 的通知!"); break; default: break; } } else { LOGGER.info("Instance {} ({}) {}", instance.getRegistration().getName(), event.getInstance(), event.getType()); } }); } }
源碼:https://github.com/gf-huanchupk/SpringBootLearning/tree/master/springboot-admin
歡迎關注個人公衆號《程序員果果》,關注有驚喜~~