1. 程式人生 > >Spring Boot (九): 微服務應用監控 Spring Boot Actuator 詳解

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 彙總而成的,彙總的演算法是:

  1. 設定狀態碼順序:setStatusOrder(Status.DOWN, Status.OUT_OF_SERVICE, Status.UP, Status.UNKNOWN);
  2. 過濾掉不能識別的狀態碼。
  3. 如果無任何狀態碼,整個 Spring Boot 應用的狀態是 UNKNOWN。
  4. 將所有收集到的狀態碼按照 1 中的順序排序。
  5. 返回有序狀態碼序列中的第一個狀態碼,作為整個 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