1. 程式人生 > >SpringBoot如何利用Actuator來監控應用?

SpringBoot如何利用Actuator來監控應用?

[toc] ## Actuator是什麼? > 官網:[Spring Boot Actuator: Production-ready Features](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#production-ready) 先從官網摘幾句文縐縐的解釋: - SpringBoot可以幫助你再將應用程式推向生產環境時對其進行監視和管理。 - 你可以選擇使用http斷點或JMX來管理和監視應用程式。 - 審計【auditing】、健康【health】和指標收集【metrics gathering】可以自動應用到你的應用程式中。 總結一下就是:Actuator就是用來監控你的應用程式的。 ## 快速開始 ### 引入依賴 ```xml org.springframework.boot
spring-boot-starter-actuator
org.springframework.boot spring-boot-starter-web ``` 一般來說這兩個依賴都是相互配合的。 ### yml與自動配置 下面是一段yml的配置: ```yml server: port: 8081 management: endpoints: web: base-path: /actuator # Actuator 提供的 API 介面的根目錄 exposure: include: '*' # 需要開放的端點 exclude: # 需要排除的端點 ``` - `management.endpoints.web`對應的配置類是:`org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties`。 - 相關的自動配置在`org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration`中完成,感興趣的同學可以檢視一下原始碼。 - basePath是Actuator提供的API介面的根目錄,預設配置就是`/actuator`。 - Exposure.include表示需要開放的端點,預設只打開`health`和`info`兩個斷點,設定`*`可以開放所有端點 。 - Exposure.include表示排除的端點,設定`*`為排除所有的端點。 ### 主程式類 ```java @SpringBootApplication public class SpringBootActuatorApplication { public static void main(String[] args) { SpringApplication.run(SpringBootActuatorApplication.class, args); } } ``` ### 測試 訪問`http://localhost:8081/actuator/health`,得到應用的健康資訊如下: ```json { status: "UP" // 開啟 } ``` ## Endpoints 由於我們設定開放了所有的Endpoints,啟動程式時,我們能夠看到控制檯輸出: ```plain [ restartedMain] o.s.b.a.e.web.EndpointLinksResolver : Exposing 13 endpoint(s) beneath base path '/actuator' ``` 說的很清楚,總共暴露了內建的13個端點,這些端點,SpringBoot文件已經交代地非常詳細啦。 其實內建的端點不止13個,官方文件說:每個端點可以被`enabled or disabled`和`exposed over HTTP or JMX`。只有當端點同時enabled和exposed的時候才可用,內建的端點也只有在自動配置生效的時候才可用。 大多數的應用程式會選擇HTTP暴露端點,我們可以通過`/actuator/health`訪問ID為`health`的端點。 ### 官方列舉的所有端點列表 JMX和web共有的 | ID | Description | | :----------------- | :----------------------------------------------------------- | | `auditevents` | 顯示當前應用程式的審計事件資訊,需要 `AuditEventRepository` bean. | | `beans` | 展示你應用程式中Spring Beans的完整列表 | | `caches` | 顯示可用快取資訊 | | `conditions` | 顯示自動裝配類的狀態及是否匹配 | | `configprops` | 顯示所有`@ConfigurationProperties`列表 | | `env` | 顯示`ConfigurableEnvironment`中的屬性 | | `flyway` | 顯示Flyway資料庫遷移資訊,需要一個或多個 `Flyway` beans | | `health` | 顯示應用的健康資訊(未認證只顯示status,認證顯示全部資訊詳情) | | `httptrace` | 顯示HTTP跟蹤資訊(預設顯示最後100個HTTP請求 - 響應交換),需要一個 `HttpTraceRepository` bean. | | `info` | 顯示任意的應用資訊 | | `integrationgraph` | 顯示Spring Integration圖,需要 `spring-integration-core`依賴 | | `loggers` | 顯示和修改應用程式中日誌記錄器的配置。 | | `liquibase` | 展示Liquibase 資料庫遷移,需要一個或多個 `Liquibase` beans. | | `metrics` | 展示當前應用的 metrics 資訊 | | `mappings` | 顯示所有`@RequestMapping` 路徑集列表 | | `scheduledtasks` | 顯示應用程式中的計劃任務 | | `sessions` | 允許從Spring會話支援的會話儲存中檢索和刪除使用者會話。 需要一個 `Servlet-based web application` using Spring Session. | | `shutdown` | 允許應用以優雅的方式關閉(預設情況下不啟用) | | `startup` | 顯示由`ApplicationStartup`收集的啟動步驟. 將 `SpringApplication` 配置為`BufferingApplicationStartup`. | | `threaddump` | 執行一個執行緒dump | 如果你的是web應用 (Spring MVC, Spring WebFlux, or Jersey),你可以使用下面這些額外的端點: | ID | Description | | :----------- | :----------------------------------------------------------- | | `heapdump` | 返回一個 `hprof` 堆轉儲檔案 | | `jolokia` | 通過HTTP公開JMXbean 當Jolokia在類路徑上時,不適用於WebFlux). 需要 `jolokia-core`依賴 | | `logfile` | 返回日誌檔案的內容(如果 `logging.file.name` 或`logging.file.path` 屬性已經被設定) 支援使用HTTP`range`標頭來檢索部分日誌檔案的內容 | | `prometheus` | 以Prometheus伺服器可以抓取的格式公開指標。 需要依賴於`micrometer-registry-prometheus`。 | ### 啟動端點 如果你希望啟動某個端點,你可以按照`management.endpoint..enabled`的配置啟動,以`shutdown`端點為例: ```yml management: endpoint: shutdown: enabled: true ``` 如果你只希望啟動某個端點,你可以向下面這樣: ```yml management: endpoints: enabled-by-default: false # 不啟用預設配置 endpoint: info: enabled: true ``` 這個示例,只會啟用info端點。 ### 暴露端點 端點可能會包含銘感資訊,考慮暴露的時候應當慎重考慮。 - web程式預設暴露的端點有且僅有兩個:`health`和`info`。 - JMX程式預設暴露所有的端點。 我們可以使用`include`和`exclude`屬性來控制端點是否需要暴露。下面是兩個例子 一、不讓JMX暴露所有端點,只讓它暴露`health`和`info`兩個端點。 ```yml management: endpoints: jmx: exposure: include: "health,info" ``` 二、暴露web除`env`和`beans`之外的所有端點。 ```yml management: endpoints: web: exposure: include: "*" exclude: "env,beans" ``` ```properties management.endpoints.web.exposure.include=* management.endpoints.web.exposure.exclude=env,beans ``` ### 配置端點 端點將會自動快取對不帶任何引數的讀取操作的響應。你可以使用`cache.time-to-live`屬性配置。 以下示例將Bean端點的快取的生存時間設定為10秒。 ```yml management: endpoint: beans: cache: time-to-live: "10s" ``` ### 發現頁面 預設你可以訪問`/actuator`頁面獲得所有的端點資訊: ```json { _links: { self: { href: "http://localhost:8081/actuator", templated: false }, health: { href: "http://localhost:8081/actuator/health", templated: false }, health-path: { href: "http://localhost:8081/actuator/health/{*path}", templated: true }, info: { href: "http://localhost:8081/actuator/info", templated: false } } } ``` ### 跨域支援 預設情況下,CORS支援是禁用的,並且僅在設定了`management.endpoints.web.cors.allowed-origins`屬性後才啟用。 以下配置允許來自example.com域的GET和POST呼叫: ```yml management: endpoints: web: cors: allowed-origins: "https://example.com" allowed-methods: "GET,POST" ``` 完整的選項可以檢視:[CorsEndpointProperties](https://github.com/spring-projects/spring-boot/tree/v2.4.1/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/CorsEndpointProperties.java) ## 實現一個定義的端點 我們直接來看一個例子吧: ```java @Component // 讓Spring容器管理 @Endpoint(id = "myEndPoint") //web和jmx公用, @WebEndpoint表示指定web public class MyEndpoint { Runtime runtime = Runtime.getRuntime(); @ReadOperation // 讀操作 public Map getData() { Map map = new HashMap<>(); map.put("available-processors", runtime.availableProcessors()); map.put("free-memory", runtime.freeMemory()); map.put("max-memory", runtime.maxMemory()); map.put("total-memory", runtime.totalMemory()); return map; } } ``` - `@Component`表明讓這個bean給Spring容器管理。 - `@Endpoint`標註這是個端點,類似的還有`@WebEndpoint`標註的是特指web程式。 - `id = "myEndPoint"`限制訪問端點的路徑:`/actuator/myEndPoint`。 - `@ReadOperation`規定HTTP請求的方法為GET,`@ReadOperation`為POST,`@DeleteOperation`為DELETE。 接下來我們測試一下,再測試之前,不要忘了yml中啟動設定: ```yml server: port: 8081 management: endpoints: web: exposure: include: '*' # 需要開放的端點。預設值只打開 health 和 info 兩個端點。通過設定 * enabled-by-default: false endpoint: myEndPoint: enabled: true ``` 我們暫時關閉其他所有的端點,只關注myEndPoint端點,接著啟動程式,訪問:`http://localhost:8081/actuator/myEndPoint`,獲得json資訊。 ```json { max-memory: 3787980800, free-memory: 235775968, available-processors: 4, total-memory: 298844160 } ``` 實際上如果是用於SpringMVC或Spring WebFlux,我們可以使用`@RestControllerEndpoint`或`@ControllerEndpoint`註解,定義一個更符合我們平時web開發模式的端點,你可以看一下下面這個例子。 ```java @Component @RestControllerEndpoint(id = "web") public class MyWebEndPoint { @GetMapping("/") public Map getData() { // ... return map; } } ``` ## Health端點 端點這麼多,我們挑幾個學習一下,`health`作為預設開放的端點之一,還是需要好好了解一下的。 ### 設定何時顯示資訊 你可以使用得到的健康資訊去檢查你的應用程式,暴露的health資訊依賴於下面兩個屬性配置: ```plain management.endpoint.health.show-details management.endpoint.health.show-components ``` 這兩個屬性可以設定的值如下: | Name | Description | | :---------------- | :---------------------------------------------------- | | `never` | 永遠不顯示 | | `when-authorized` | 需要授權,通過 `management.endpoint.health.roles`配置 | | `always` | 對所有使用者顯示 | health端點通過健康指示器`HealthIndicator`獲取不同的資源的健康資訊,且Autuator內建了多個HealthIndicator的實現,太多啦太多啦,如果需要可以看看官網 [Auto-configured HealthIndicators](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#production-ready-health-indicators)。 另外,如果你想啟用或者禁用指定的指示器,你可以配置`management.health.key.enabled`,key需要被替換,官網表格上有。 如果你想設定全部的,你可以配置`management.health.defaults.enabled` ### 設定順序 你可以通過以下設定顯示順序: ```yml management: endpoint: health: status: order: "fatal,down,out-of-service,unknown,up" ``` ### 設定響應碼 響應碼反應了總體健康狀態。預設情況下,`OUT_OF_SERVICE`和`DOWN`的對映為503,其他狀態為200。你可以按照下面的方式設定對映: ```yml management: endpoint: health: status: http-mapping: down: 503 fatal: 503 out-of-service: 503 ``` ### 自定義健康資訊 縱使,Actuator已經提供了許多內建實現,總會滿足不了我們的需求,那如何去自定義呢? - 註冊實現HealthIndicator介面的Spring Bean。 - 提供health()方法的實現並返回健康響應,包括狀態和其他需要顯示的詳細資訊。 以下程式碼展示了一個案例: ```java import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.stereotype.Component; import java.util.Random; @Component public class MyHealthIndicator implements HealthIndicator { @Override public Health health() { // perform some specific health check boolean check = check(); if (!check) { return Health.down().withDetail("Error Code", 0).build(); } return Health.up().build(); } private boolean check() { return new Random().nextBoolean(); } } ``` > id就是bena的名稱去掉HealthIndicator字尾,這裡id就是my。 看看相關的yml怎麼配置? ```yml management: endpoints: web: exposure: include: '*' # 需要開放的端點。預設值只打開 health 和 info 兩個端點。通過設定 * ,可以開放所有端點。 enabled-by-default: false endpoint: health: enabled: true show-details: always # 何時顯示完整的健康資訊 show-components: always status: http-mapping: # 設定不同健康狀態對應的響應狀態碼 DOWN: 503 order: FATAL, DOWN, OUT_OF_SERVICE, UP, UNKNOWN # 狀態排序 ``` 測試一下,訪問:`/actuator/health`,可以嘗試多點幾次,會出現UP和DOWN的情況,得到以下資訊: ```json { status: "DOWN", components: { diskSpace: { status: "UP", details: { total: 267117391872, free: 130840469504, threshold: 10485760, exists: true } }, my: { status: "DOWN", details: { Error Code: 0 } }, ping: { status: "UP" } } } ``` - my對應的就是我們自定義的MyHealthIndicator,裡面詳細的資訊有:狀態status,資訊details。 - diskSpace對應DiskSpaceHealthIndicator,ping對應的是PingHealthIndicator。 其他的端點,感興趣的小夥伴可以去到官網一一測試,總之,通過這些Actuator提供的端點,我們很容易就能夠監控管理我們的應用程式。 ## 原始碼下載 本文內容均為對優秀部落格及官方文件總結而得,原文地址均已在文中參考閱讀處標註。最後,文中的程式碼樣例已經全部上傳至Gitee:[https://gitee.com/tqbx/springboot-samples-learn](https://gitee.com/tqbx/springboot-samples-learn)。 ## 參考閱讀 - [Spring Boot Actuator: Production-ready Features](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#production-ready) - [SpringBoot重點詳解--使用Actuator進行健康監控](https://blog.csdn.net/pengjunlee/article/details/8