前言
springboot專案部署起來後,如何實時監控專案的執行狀況呢?本文記錄使用springboot-admin對服務進行監控。
springboot-admin介紹:https://codecentric.github.io/spring-boot-admin/current/#_what_is_spring_boot_admin
工程結構
服務端
server服務端
客戶端
client客戶端
服務端、客戶端都是獨立的web專案,服務端是監控程式,客戶端是被監控的程式,本文只測試了一個客戶端接入
程式碼編寫
服務端
server服務端引入相關依賴
2.2.0後admin的管理頁面支援中文,因此我們引入此版本(parent不再是引入我們的父工程pom了,直接引入springboot的2.2.0)
<!-- 引入admin相關依賴 2.2.0頁面支援中文顯示,需要springboot 2.2.0 -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>2.2.0</version>
</dependency>
為了安全性,引入security
<!--springboot security 安全相關-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
解決控制檯報錯,移除tomcat,改用jetty
<!--
報錯:java.lang.IllegalStateException: Calling [asyncError()] is not valid for a request with Async state [MUST_DISPATCH]
解決:移除tomcat,換成jetty
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
監控系統,直接配置賬號、密碼,不用搞那麼麻煩接入資料庫
#配置一個賬號和密碼
spring.security.user.name=admin
spring.security.user.password=123456
做好security配置
/**
* Security安全配置
*/
@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 {
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支援,admin-client註冊時需要使用
.httpBasic().and()
.csrf() //開啟基於cookie的csrf保護
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
//忽略這些路徑的csrf保護以便admin-client註冊
.ignoringAntMatchers(
adminContextPath + "/instances",
adminContextPath + "/actuator/**"
);
}
}
客戶端是要暴露actuator的web埠的,為了安全,客戶端只允許服務端請求actuator的web介面,為了方便客戶端區分請求來源,我們在請求頭注入自定義引數
/**
* 注入額外的請求頭,方便客戶端區分請求來源
*/
@Component
public class HttpHeadersProviderConfig implements HttpHeadersProvider {
@Value("${server.port}")
private String port; @Override
public HttpHeaders getHeaders(Instance instance) {
HttpHeaders httpHeaders = new HttpHeaders();
//設定約定好的請求頭引數
httpHeaders.add("spring-boot-admin-service", port);
return httpHeaders;
}
}
我們不可能整天上系統看監控資料,做好自定義通知,當例項狀態發生改變,及時通知(發郵件、企業微信、釘釘都可以,自己實現)
/**
* 自定義通知
* 繼承 AbstractStatusChangeNotifier 類,實現了 doNotify 方法,
* 當應用狀態改變的時候會回撥 doNotify 方法。
*/
@Component
public class CustomNotifierConfig extends AbstractStatusChangeNotifier { public CustomNotifierConfig(InstanceRepository repository) {
super(repository);
} @Override
protected Mono<Void> doNotify(InstanceEvent event, Instance instance) {
return Mono.fromRunnable(() -> {
if (event instanceof InstanceStatusChangedEvent) {
System.out.println("例項名稱:"+instance.getRegistration().getName());
System.out.println("例項服務地址:"+instance.getRegistration().getServiceUrl());
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:
System.out.println(status);
break;
} }
});
}
}
最後在啟動打上@EnableAdminServer註解,開啟服務監控
@EnableAdminServer//開啟AdminServer功能
@SpringBootApplication
public class SpringBootAdminServerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootAdminServerApplication.class, args);
} /**
* 啟動成功
*/
@Bean
public ApplicationRunner applicationRunner() {
return applicationArguments -> {
System.out.println("啟動成功!");
};
}
}
客戶端
服務端引入了2.2.0版本的依賴,因此客戶端也要引入2.2.0依賴
<!-- 引入admin相關依賴 -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.2.0</version>
</dependency>
在配置檔案中,開啟埠、配置admin的server地址,以及賬號、密碼
#啟用端點,預設情況下,除shutdown以外的所有端點均已啟用
management.endpoint.shutdown.enabled=true #顯示db、redis、rabbti連線情況等
management.endpoint.health.show-details=always #公開所有端點web介面
management.endpoints.web.exposure.include=* #admin-server地址,以及登入賬號、密碼
spring.boot.admin.client.port=10010
spring.boot.admin.client.url=http://localhost:${spring.boot.admin.client.port}
spring.boot.admin.client.username=admin
spring.boot.admin.client.password=123456
為了方便測試其他東西
<!--新增springdata-cache依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency> <!--新增MySQL驅動依賴 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
同時建立測試介面、定時器、cache快取、非同步任務,就是為了看服務端能否監控到
客戶端是要暴露actuator的web埠的,為了安全,客戶端只允許服務端請求actuator的web介面(通過約定好的請求頭來判斷)
/**
* 針對actuator介面做安全限制,只允許服務端呼叫
*/
@WebFilter
@ServletComponentScan
@Component
public class ActuatorFilter implements Filter {
@Value("${spring.boot.admin.client.port}")
private String adminServicePort; @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest; //判斷約定好的請求頭引數
if (request.getRequestURI().contains("/actuator") && !adminServicePort.equals(request.getHeader("spring-boot-admin-service"))){
throw new RuntimeException("抱歉,你無許可權訪問,Actuator埠受保護! Sorry, you have no permission to access it,Actuator port protected!");
} filterChain.doFilter(servletRequest, servletResponse);
}
}
效果演示
安全配置生效
首先先看安全配置都生效了沒有
訪問服務端,需要登入
登入上去,客戶端已經註冊成功
正常監控客戶端中...
瀏覽器直接訪問客戶端的actuator介面,直接丟擲異常
http://localhost:10011/actuator
其他介面正常訪問
自定義通知
注:客戶端首次在服務端註冊,並沒有觸發自定義通知
再看下自定義通知
停掉客戶端服務、重啟啟動客戶端,觸發服務端自定義通知
具體監控項
具體客戶端的監控首頁,有我們在客戶端寫的info資訊、磁碟監控、堆、非堆記憶體監控、程序、執行緒監控、垃圾回收監控
#新增描述
info.describe=SpringBootAdmin,Test Client Service!
info.author=huanzi-qch
info.version=1.0.0
計劃任務這裡可以看到我們配置的定時器
web對映可以看到所有的web介面
http跟蹤,可以檢視具體請求的響應情況
快取選單,可以看到我們使用到的快取空間
還可以下載jvm dump檔案
其他就不一一列舉,自己把專案跑起來再看
另外,這個版本好像不能檢視非同步任務?我並沒有找到相關頁面
後記
SpringBoot-Admin監控Client有兩種模式:
一種是在Client端引入spring-boot-admin-starter-client依賴,配置好Server的相關資訊。
另一種模式是將所有Client端註冊到服務發現(Eureka)元件中去,同時把Server端也註冊,這樣Server端就可以監控所有Client端了,不用對Client都新增依賴。
SpringBoot系列——admin服務監控暫時先記錄到這,後續有空再進行補充
程式碼開源
程式碼已經開源、託管到我的GitHub、碼雲:
GitHub:https://github.com/huanzi-qch/springBoot
碼雲:https://gitee.com/huanzi-qch/springBoot