在當前的微服務架構方式下,咱們會有不少的服務部署在不一樣的機器上,相互是經過服務調用的方式進行交互,一個完整的業務流程中間會通過不少個微服務的處理和傳遞,那麼,如何能知道每一個服務的健康情況就顯得尤其重要。html
萬幸的是 Spring Boot 爲咱們提供了監控模塊 Spring Boot Actuator ,本篇文章將和你們一塊兒探討一些 Spring Boot Actuator 一些常見用法方便咱們在平常的使用中對咱們的微服務進行監控治理。java
Spring Boot Actuator 幫咱們實現了對程序內部運行狀況監控,好比監控情況、Bean加載狀況、環境變量、日誌信息、線程信息等。git
使用 Spring Boot Actuator 須要加入以下依賴:github
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
複製代碼
注意: 因 Spring Boot Actuator 會暴露咱們服務的詳細信息,爲了保障安全性,建議添加安全控制的相關依賴 spring-boot-starter-security
,這樣,在訪問應用監控端點時,都須要輸入驗證信息。所需依賴以下:web
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
複製代碼
配置文件 application.yml 以下:算法
代碼清單:spring-boot-actuator/src/main/resources/application.ymlspring
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
}
}
}
複製代碼
這些是默認支持的連接,只有:json
/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
複製代碼
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信息 |
health 主要用來檢查應用的運行狀態,這是咱們使用最高頻的一個監控點。一般使用此接口提醒咱們應用實例的運行狀態,以及應用不」健康「的緣由,好比數據庫鏈接、磁盤空間不夠等。
默認狀況下 health 的狀態是開放的,添加依賴後啓動項目,訪問:http://localhost:8080/actuator/health 便可看到應用的狀態。
{
"status" : "UP"
}
複製代碼
默認狀況下,最終的 Spring Boot 應用的狀態是由 HealthAggregator
彙總而成的,彙總的算法是:
setStatusOrder(Status.DOWN, Status.OUT_OF_SERVICE, Status.UP, Status.UNKNOWN);
。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
屬性來所有禁用它們。
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"
}
}
複製代碼
啓動工程,打開瀏覽器訪問: 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 的別名、類型、是否單例、類的地址、依賴等信息。
啓動工程,打開瀏覽器訪問: 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"
}],
},
}
}
}
複製代碼
是用這個接口能夠看出應用運行時查看代碼了某個配置在什麼條件下生效,或者某個自動配置爲何沒有生效。
這個接口首先須要在配置文件中配置開啓此功能:
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
。
這時能夠看到咱們啓動的示例工程已經關閉了。
描述所有的 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
}]
}
}
}
複製代碼
/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
}]
}
複製代碼