Spring Boot (九): 微服務應用監控 Spring Boot Actuator 詳解
1. 引言
在當前的微服務架構方式下,我們會有很多的服務部署在不同的機器上,相互是通過服務呼叫的方式進行互動,一個完整的業務流程中間會經過很多個微服務的處理和傳遞,那麼,如何能知道每個服務的健康狀況就顯得尤為重要。
萬幸的是 Spring Boot 為我們提供了監控模組 Spring Boot Actuator ,本篇文章將和大家一起探討一些 Spring Boot Actuator 一些常見用法方便我們在日常的使用中對我們的微服務進行監控治理。
Spring Boot Actuator 幫我們實現了對程式內部執行情況監控,比如監控狀況、Bean載入情況、環境變數、日誌資訊、執行緒資訊等。
2. Actuator 的使用
2.1 工程依賴
使用 Spring Boot Actuator 需要加入如下依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
注意: 因 Spring Boot Actuator 會暴露我們服務的詳細資訊,為了保障安全性,建議新增安全控制的相關依賴 spring-boot-starter-security
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2.2 工程配置
配置檔案 application.yml 如下:
程式碼清單:spring-boot-actuator/src/main/resources/application.yml
***
server: port: 8080 info: app: name: spring-boot-actuator version: 1.0.0 spring: security: user: name: admin password: admin
現在先啟動工程,開啟瀏覽器訪問:http://localhost:8080/actuator ,可以看到頁面顯示如下 json :
{
"_links":{
"self":{
"href":"http://localhost:8080/actuator",
"templated":false
},
"health":{
"href":"http://localhost:8080/actuator/health",
"templated":false
},
"health-component-instance":{
"href":"http://localhost:8080/actuator/health/{component}/{instance}",
"templated":true
},
"health-component":{
"href":"http://localhost:8080/actuator/health/{component}",
"templated":true
},
"info":{
"href":"http://localhost:8080/actuator/info",
"templated":false
}
}
}
這些是預設支援的連結,只有:
/actuator
/actuator/health
/health/{component}/{instance}
/health/{component}
/actuator/info
我們可以在配置檔案 application.yml 中增加配置來開啟更多的監控資訊:
management:
endpoints:
web:
exposure:
include: '*'
# base-path: /monitor
endpoint:
health:
show-details: always
shutdown:
enabled: true
management.endpoints.web.exposure.include='*'
代表開啟全部監控,當然也可以配置需要開啟的監控,如:management.endpoints.web.exposure.include=beans,trace
。management.endpoint.health.show-details=always
含義是 health endpoint 是開啟顯示全部細節。預設情況下, /actuator/health 是公開的,並且不顯示細節。management.endpoints.web.base-path=/monitor
代表啟用單獨的url地址來監控 Spring Boot 應用,預設的路徑是/actuator/*
,如果開啟此配置,重啟後再次訪問路徑就會變成/manage/*
。management.endpoint.shutdown.enabled=true
啟用介面關閉 Spring Boot 。
在某些業務場景下,我們的監控資訊可能會需要跨越獲取, Spring Boot Actuator 提供了 CORS 相關的配置,來支援跨域呼叫,預設情況下,CORS 支援處於禁用狀態,只有在設定了 management.endpoints.web.cors.allowed-origins
屬性後才能啟用。以下配置允許來自 https://www.geekdigging.com
域的 GET 和 POST 呼叫:
management:
endpoints:
web:
cors:
allowed-origins: https://www.geekdigging.com
allowed-methods: GET,POST
2.3 REST 介面
Spring Boot Actuator 為我們提供了非常豐富的監控介面,可以通過它們瞭解應用程式執行時的內部狀況。同時 Actuator 支援使用者自定義新增端點,使用者可以根據自己的實際應用,定義一些比較關心的指標,在執行期進行監控。
HTTP 方法 | 路徑 | 描述 |
---|---|---|
GET | /auditevents | 顯示當前應用程式的審計事件資訊 |
GET | /beans | 顯示一個應用中所有Spring Beans的完整列表 |
GET | /conditions | 顯示配置類和自動配置類(configuration and auto-configuration classes)的狀態及它們被應用或未被應用的原因 |
GET | /configprops | 顯示一個所有@ConfigurationProperties的集合列表 |
GET | /env | 顯示來自Spring的 ConfigurableEnvironment的屬性 |
GET | /flyway | 顯示資料庫遷移路徑,如果有的話 |
GET | /health | 顯示應用的健康資訊(當使用一個未認證連線訪問時顯示一個簡單的’status’,使用認證連線訪問則顯示全部資訊詳情) |
GET | /info | 顯示任意的應用資訊 |
GET | /liquibase | 展示任何Liquibase資料庫遷移路徑,如果有的話 |
GET | /metrics | 展示當前應用的metrics資訊 |
GET | /mappings | 顯示一個所有@RequestMapping路徑的集合列表 |
GET | /scheduledtasks | 顯示應用程式中的計劃任務 |
GET | /sessions | 允許從Spring會話支援的會話儲存中檢索和刪除(retrieval and deletion)使用者會話。使用Spring Session對反應性Web應用程式的支援時不可用。 |
POST | /shutdown | 允許應用以優雅的方式關閉(預設情況下不啟用) |
GET | /threaddump | 執行一個執行緒dump |
如果使用web應用(Spring MVC, Spring WebFlux, 或者 Jersey),還可以使用以下介面:
HTTP 方法 | 路徑 | 描述 |
---|---|---|
GET | /heapdump | 返回一個GZip壓縮的hprof堆dump檔案 |
GET | /jolokia | 通過HTTP暴露JMX beans(當Jolokia在類路徑上時,WebFlux不可用) |
GET | /logfile | 返回日誌檔案內容(如果設定了logging.file或logging.path屬性的話),支援使用HTTP Range頭接收日誌檔案內容的部分資訊 |
GET | /prometheus | 以可以被Prometheus伺服器抓取的格式顯示metrics資訊 |
3. 介面詳解
3.1 /health
health 主要用來檢查應用的執行狀態,這是我們使用最高頻的一個監控點。通常使用此介面提醒我們應用例項的執行狀態,以及應用不”健康“的原因,比如資料庫連線、磁碟空間不夠等。
預設情況下 health 的狀態是開放的,新增依賴後啟動專案,訪問:http://localhost:8080/actuator/health 即可看到應用的狀態。
{
"status" : "UP"
}
預設情況下,最終的 Spring Boot 應用的狀態是由 HealthAggregator
彙總而成的,彙總的演算法是:
- 設定狀態碼順序:
setStatusOrder(Status.DOWN, Status.OUT_OF_SERVICE, Status.UP, Status.UNKNOWN);
。 - 過濾掉不能識別的狀態碼。
- 如果無任何狀態碼,整個 Spring Boot 應用的狀態是 UNKNOWN。
- 將所有收集到的狀態碼按照 1 中的順序排序。
- 返回有序狀態碼序列中的第一個狀態碼,作為整個 Spring Boot 應用的狀態。
Health 通過合併幾個健康指數檢查應用的健康情況。Spring Boot Actuator 會自動配置以下內容:
名稱 | 描述 |
---|---|
CassandraHealthIndicator | 檢查Cassandra資料庫是否已啟動。 |
CouchbaseHealthIndicator | 檢查Couchbase群集是否已啟動。 |
DiskSpaceHealthIndicator | 檢查磁碟空間不足。 |
DataSourceHealthIndicator | 檢查是否可以建立連線 DataSource 。 |
ElasticsearchHealthIndicator | 檢查Elasticsearch叢集是否已啟動。 |
InfluxDbHealthIndicator | 檢查InfluxDB伺服器是否已啟動。 |
JmsHealthIndicator | 檢查JMS代理是否啟動。 |
MailHealthIndicator | 檢查郵件伺服器是否已啟動。 |
MongoHealthIndicator | 檢查Mongo資料庫是否已啟動。 |
Neo4jHealthIndicator | 檢查Neo4j伺服器是否已啟動。 |
RabbitHealthIndicator | 檢查Rabbit伺服器是否已啟動。 |
RedisHealthIndicator | 檢查Redis伺服器是否啟動。 |
SolrHealthIndicator | 檢查Solr伺服器是否已啟動。 |
可以通過設定 management.health.defaults.enabled
屬性來全部禁用它們。
3.2 /info
info 就是我們自己在配置檔案中配置的以 info 開頭的資訊,如我們在示例工程中配置的:
info:
app:
name: spring-boot-actuator
version: 1.0.0
啟動工程,開啟瀏覽器訪問: http://localhost:8080/actuator/info
,結果如下:
{
"app":{
"name":"spring-boot-actuator",
"version":"1.0.0"
}
}
3.3 /beans
啟動工程,開啟瀏覽器訪問: http://localhost:8080/actuator/beans
,部分結果如下:
{
"contexts": {
"application": {
"beans": {
"endpointCachingOperationInvokerAdvisor": {
"aliases": [],
"scope": "singleton",
"type": "org.springframework.boot.actuate.endpoint.invoker.cache.CachingOperationInvokerAdvisor",
"resource": "class path resource [org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.class]",
"dependencies": ["environment"]
},
"defaultServletHandlerMapping": {
"aliases": [],
"scope": "singleton",
"type": "org.springframework.web.servlet.HandlerMapping",
"resource": "class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]",
"dependencies": []
},
},
"parentId": null
}
}
}
從中可以看到,這個介面展現了 bean 的別名、型別、是否單例、類的地址、依賴等資訊。
3.4 /conditions
啟動工程,開啟瀏覽器訪問: http://localhost:8080/actuator/conditions
,部分結果如下:
{
"contexts": {
"application": {
"positiveMatches": {
"AuditAutoConfiguration#auditListener": [{
"condition": "OnBeanCondition",
"message": "@ConditionalOnMissingBean (types: org.springframework.boot.actuate.audit.listener.AbstractAuditListener; SearchStrategy: all) did not find any beans"
}],
"AuditAutoConfiguration#authenticationAuditListener": [{
"condition": "OnClassCondition",
"message": "@ConditionalOnClass found required class 'org.springframework.security.authentication.event.AbstractAuthenticationEvent'"
}, {
"condition": "OnBeanCondition",
"message": "@ConditionalOnMissingBean (types: org.springframework.boot.actuate.security.AbstractAuthenticationAuditListener; SearchStrategy: all) did not find any beans"
}],
},
}
}
}
是用這個介面可以看出應用執行時檢視程式碼了某個配置在什麼條件下生效,或者某個自動配置為什麼沒有生效。
3.5 /shutdown
這個介面首先需要在配置檔案中配置開啟此功能:
management.endpoint.shutdown.enabled=true
配置完成後,可以使用 curl 模擬 post 請求此介面:
curl -X POST "http://localhost:8080/actuator/shutdown"
顯示結果為:
{
"message": "Shutting down, bye..."
}
注意:示例工程添加了 spring-boot-starter-security
,直接使用 post 訪問此介面會響應 401 ,表示無許可權訪問,如需測試此介面,請暫時先關閉 spring-boot-starter-security
。
這時可以看到我們啟動的示例工程已經關閉了。
3.6 /mappings
描述全部的 URI 路徑,以及它們和控制器的對映關係
啟動工程,開啟瀏覽器訪問: http://localhost:8080/actuator/mappings
,部分結果如下:
{
"handler": "Actuator web endpoint 'beans'",
"predicate": "{GET /actuator/beans, produces [application/vnd.spring-boot.actuator.v2+json || application/json]}",
"details": {
"handlerMethod": {
"className": "org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping.OperationHandler",
"name": "handle",
"descriptor": "(Ljavax/servlet/http/HttpServletRequest;Ljava/util/Map;)Ljava/lang/Object;"
},
"requestMappingConditions": {
"consumes": [],
"headers": [],
"methods": ["GET"],
"params": [],
"patterns": ["/actuator/beans"],
"produces": [{
"mediaType": "application/vnd.spring-boot.actuator.v2+json",
"negated": false
}, {
"mediaType": "application/json",
"negated": false
}]
}
}
}
3.7 /threaddump
/threaddump 介面會生成當前執行緒活動的快照。這個功能非常好,方便我們在日常定位問題的時候檢視執行緒的情況。 主要展示了執行緒名、執行緒ID、執行緒的狀態、是否等待鎖資源等資訊。
啟動工程,開啟瀏覽器訪問: http://localhost:8080/actuator/threaddump
,部分結果如下:
{
"threads": [{
"threadName": "Reference Handler",
"threadId": 2,
"blockedTime": -1,
"blockedCount": 2,
"waitedTime": -1,
"waitedCount": 0,
"lockName": null,
"lockOwnerId": -1,
"lockOwnerName": null,
"daemon": true,
"inNative": false,
"suspended": false,
"threadState": "RUNNABLE",
"priority": 10,
"stackTrace": [{
"classLoaderName": null,
"moduleName": "java.base",
"moduleVersion": "11.0.4",
"methodName": "waitForReferencePendingList",
"fileName": "Reference.java",
"lineNumber": -2,
"className": "java.lang.ref.Reference",
"nativeMethod": true
}
...
"lockedMonitors": [],
"lockedSynchronizers": [{
"className": "java.util.concurrent.locks.ReentrantLock$NonfairSync",
"identityHashCode": 2060076420
}],
"lockInfo": null
...
{
"threadName": "DestroyJavaVM",
"threadId": 42,
"blockedTime": -1,
"blockedCount": 0,
"waitedTime": -1,
"waitedCount": 0,
"lockName": null,
"lockOwnerId": -1,
"lockOwnerName": null,
"daemon": false,
"inNative": false,
"suspended": false,
"threadState": "RUNNABLE",
"priority": 5,
"stackTrace": [],
"lockedMonitors": [],
"lockedSynchronizers": [],
"lockInfo": null
}]
}
4. 示例程式碼
示例程式碼-Github
示例程式碼-Gitee
5. 參考:
使用 Spring Boot Actuator 監控應用
Spring Boot 官方文件之 Actua