端點
Actuator 端點允許您監控應用程式並與其互動。Spring Boot 包含許多內建端點,並允許您新增自己的端點。例如,health 端點提供基本的應用程式健康資訊。
您可以控制對每個獨立端點的訪問,並透過 HTTP 或 JMX 暴露(使其可遠端訪問)這些端點。當允許訪問且已暴露時,端點被認為是可用的。內建端點僅在可用時自動配置。大多數應用程式選擇透過 HTTP 暴露,其中端點的 ID 和 /actuator 字首對映到 URL。例如,預設情況下,health 端點對映到 /actuator/health。
| 要了解有關 Actuator 端點及其請求和響應格式的更多資訊,請參閱API 文件。 |
以下與技術無關的端點可用
| ID | 描述 |
|---|---|
|
公開當前應用程式的審計事件資訊。需要一個 |
|
顯示應用程式中所有 Spring bean 的完整列表。 |
|
公開可用的快取。 |
|
顯示在配置和自動配置類上評估的條件,以及它們匹配或不匹配的原因。 |
|
顯示所有 |
|
公開 Spring 的 |
|
顯示已應用的任何 Flyway 資料庫遷移。需要一個或多個 |
|
顯示應用程式健康資訊。 |
|
顯示 HTTP 交換資訊(預設情況下,最後 100 個 HTTP 請求-響應交換)。需要一個 |
|
顯示任意應用程式資訊。 |
|
顯示 Spring Integration 圖。需要依賴 |
|
顯示和修改應用程式中日誌記錄器的配置。 |
|
顯示已應用的任何 Liquibase 資料庫遷移。需要一個或多個 |
|
顯示當前應用程式的“度量”資訊,以診斷應用程式已記錄的度量。 |
|
顯示所有 |
|
顯示 Quartz 排程器作業的資訊。受 清理 約束。 |
|
顯示應用程式中的排程任務。 |
|
允許從 Spring Session 支援的會話儲存中檢索和刪除使用者會話。需要使用 Spring Session 的基於 servlet 的 Web 應用程式。 |
|
允許應用程式優雅關閉。僅在使用 jar 打包時有效。預設停用。 |
|
顯示 啟動步驟資料,這些資料由 |
|
執行執行緒轉儲。 |
如果您的應用程式是 Web 應用程式(Spring MVC、Spring WebFlux 或 Jersey),您可以使用以下附加端點
| ID | 描述 |
|---|---|
|
返回堆轉儲檔案。在 HotSpot JVM 上,返回 |
|
返回日誌檔案內容(如果已設定 |
|
以 Prometheus 伺服器可抓取的格式公開指標。需要依賴 |
控制對端點的訪問
預設情況下,除 shutdown 和 heapdump 之外的所有端點都可無限制訪問。要配置允許訪問端點,請使用其 management.endpoint.<id>.access 屬性。以下示例允許無限制訪問 shutdown 端點
-
屬性
-
YAML
management.endpoint.shutdown.access=unrestricted
management:
endpoint:
shutdown:
access: unrestricted
如果您更喜歡選擇性加入而不是選擇性退出訪問,請將 management.endpoints.access.default 屬性設定為 none,並使用單獨的端點 access 屬性選擇性加入。以下示例允許對 loggers 端點進行只讀訪問,並拒絕訪問所有其他端點
-
屬性
-
YAML
management.endpoints.access.default=none
management.endpoint.loggers.access=read-only
management:
endpoints:
access:
default: none
endpoint:
loggers:
access: read-only
無法訪問的端點將完全從應用程式上下文中移除。如果您只想更改端點公開的技術,請使用 include 和 exclude 屬性。 |
限制訪問
可以使用 management.endpoints.access.max-permitted 屬性限制應用程式範圍的端點訪問。此屬性優先於預設訪問或單個端點的訪問級別。將其設定為 none 以使所有端點都不可訪問。將其設定為 read-only 以僅允許對端點進行讀取訪問。
對於 @Endpoint、@JmxEndpoint 和 @WebEndpoint,讀取訪問等同於用 @ReadOperation 註解的端點方法。對於 @ControllerEndpoint 和 @RestControllerEndpoint,讀取訪問等同於可以處理 GET 和 HEAD 請求的請求對映。對於 @ServletEndpoint,讀取訪問等同於 GET 和 HEAD 請求。
公開端點
預設情況下,只有 health 端點透過 HTTP 和 JMX 公開。由於端點可能包含敏感資訊,您應仔細考慮何時公開它們。
要更改公開的端點,請使用以下特定於技術的 include 和 exclude 屬性
| 財產 | 預設值 |
|---|---|
|
|
|
|
|
|
|
|
include 屬性列出了要公開的端點的 ID。exclude 屬性列出了不應公開的端點的 ID。exclude 屬性優先於 include 屬性。您可以同時使用端點 ID 列表配置 include 和 exclude 屬性。
例如,要僅透過 JMX 公開 health 和 info 端點,請使用以下屬性
-
屬性
-
YAML
management.endpoints.jmx.exposure.include=health,info
management:
endpoints:
jmx:
exposure:
include: "health,info"
* 可用於選擇所有端點。例如,要透過 HTTP 公開所有端點,除了 env 和 beans 端點,請使用以下屬性
-
屬性
-
YAML
management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=env,beans
management:
endpoints:
web:
exposure:
include: "*"
exclude: "env,beans"
* 在 YAML 中有特殊含義,因此如果要包含(或排除)所有端點,請務必新增引號。 |
| 如果您的應用程式是公開的,我們強烈建議您也保護您的端點。 |
如果您想實現自己的端點公開策略,可以註冊一個 EndpointFilter bean。 |
安全
出於安全考慮,預設情況下只有 /health 端點透過 HTTP 公開。您可以使用 management.endpoints.web.exposure.include 屬性配置要公開的端點。
在設定 management.endpoints.web.exposure.include 之前,請確保公開的 Actuator 不包含敏感資訊,並透過防火牆保護或透過 Spring Security 等方式保護。 |
如果 Spring Security 在類路徑中且沒有其他 SecurityFilterChain bean,則除 /health 之外的所有 Actuator 都由 Spring Boot 自動配置保護。如果您定義自定義 SecurityFilterChain bean,Spring Boot 自動配置將回退,讓您完全控制 Actuator 訪問規則。
如果您希望為 HTTP 端點配置自定義安全性(例如,只允許具有特定角色的使用者訪問它們),Spring Boot 提供了一些方便的 RequestMatcher 物件,您可以將其與 Spring Security 結合使用。
典型的 Spring Security 配置可能如下所示
-
Java
-
Kotlin
import org.springframework.boot.security.autoconfigure.actuate.web.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import static org.springframework.security.config.Customizer.withDefaults;
@Configuration(proxyBeanMethods = false)
public class MySecurityConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) {
http.securityMatcher(EndpointRequest.toAnyEndpoint());
http.authorizeHttpRequests((requests) -> requests.anyRequest().hasRole("ENDPOINT_ADMIN"));
http.httpBasic(withDefaults());
return http.build();
}
}
import org.springframework.boot.security.autoconfigure.actuate.web.servlet.EndpointRequest
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.Customizer.withDefaults
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.web.SecurityFilterChain
@Configuration(proxyBeanMethods = false)
class MySecurityConfiguration {
@Bean
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
http.securityMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests { requests ->
requests.anyRequest().hasRole("ENDPOINT_ADMIN")
}
http.httpBasic(withDefaults())
return http.build()
}
}
前面的示例使用 EndpointRequest.toAnyEndpoint() 匹配對任何端點的請求,然後確保所有請求都具有 ENDPOINT_ADMIN 角色。EndpointRequest 上還提供了其他幾個匹配器方法。有關詳細資訊,請參閱 API 文件。
如果您將應用程式部署在防火牆後面,您可能希望所有 Actuator 端點都可以在不需要身份驗證的情況下訪問。您可以透過更改 management.endpoints.web.exposure.include 屬性來實現,如下所示
-
屬性
-
YAML
management.endpoints.web.exposure.include=*
management:
endpoints:
web:
exposure:
include: "*"
此外,如果存在 Spring Security,您需要新增自定義安全配置,允許未經身份驗證的使用者訪問端點,如下例所示
-
Java
-
Kotlin
import org.springframework.boot.security.autoconfigure.actuate.web.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration(proxyBeanMethods = false)
public class MySecurityConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) {
http.securityMatcher(EndpointRequest.toAnyEndpoint());
http.authorizeHttpRequests((requests) -> requests.anyRequest().permitAll());
return http.build();
}
}
import org.springframework.boot.security.autoconfigure.actuate.web.servlet.EndpointRequest
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.web.SecurityFilterChain
@Configuration(proxyBeanMethods = false)
class MySecurityConfiguration {
@Bean
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
http.securityMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests { requests ->
requests.anyRequest().permitAll()
}
return http.build()
}
}
在前面的兩個示例中,配置僅適用於 Actuator 端點。由於 Spring Boot 的安全配置在存在任何 SecurityFilterChain bean 時完全回退,您需要配置一個額外的 SecurityFilterChain bean,其中包含適用於應用程式其餘部分的規則。 |
跨站請求偽造保護
由於 Spring Boot 依賴 Spring Security 的預設值,因此預設情況下啟用 CSRF 保護。這意味著,當使用預設安全配置時,需要 POST(關閉和日誌記錄器端點)、PUT 或 DELETE 的 Actuator 端點會收到 403(禁止)錯誤。
| 我們建議僅當您建立的服務由非瀏覽器客戶端使用時,才完全停用 CSRF 保護。 |
您可以在 Spring Security 參考指南 中找到有關 CSRF 保護的更多資訊。
配置端點
端點自動快取對不帶任何引數的讀取操作的響應。要配置端點快取響應的時間量,請使用其 cache.time-to-live 屬性。以下示例將 beans 端點快取的生存時間設定為 10 秒
-
屬性
-
YAML
management.endpoint.beans.cache.time-to-live=10s
management:
endpoint:
beans:
cache:
time-to-live: "10s"
management.endpoint.<name> 字首唯一標識正在配置的端點。 |
清理敏感值
/env、/configprops 和 /quartz 端點返回的資訊可能是敏感的,因此預設情況下值總是完全清理(替換為 ******)。
僅在以下情況下才能以未清理的形式檢視值
-
show-values屬性已設定為never以外的值 -
沒有自定義
SanitizingFunctionbean 適用
可清理端點的 show-values 屬性可以配置為以下值之一
-
never- 值始終完全清理(替換為******) -
always- 值顯示給所有使用者(只要沒有SanitizingFunctionbean 適用) -
when-authorized- 值僅顯示給授權使用者(只要沒有SanitizingFunctionbean 適用)
對於 HTTP 端點,如果使用者已透過身份驗證並具有端點角色屬性配置的角色,則被視為已授權。預設情況下,任何經過身份驗證的使用者都被授權。
對於 JMX 端點,所有使用者始終被授權。
以下示例允許所有具有 admin 角色的使用者以原始形式檢視 /env 端點中的值。未經授權的使用者或沒有 admin 角色的使用者將只看到已清理的值。
-
屬性
-
YAML
management.endpoint.env.show-values=when-authorized
management.endpoint.env.roles=admin
management:
endpoint:
env:
show-values: when-authorized
roles: "admin"
此示例假設尚未定義任何 SanitizingFunction bean。 |
Actuator Web 端點的超媒體
添加了一個“發現頁面”,其中包含所有端點的連結。“發現頁面”預設在 /actuator 上可用。
要停用“發現頁面”,請將以下屬性新增到您的應用程式屬性中
-
屬性
-
YAML
management.endpoints.web.discovery.enabled=false
management:
endpoints:
web:
discovery:
enabled: false
當配置了自定義管理上下文路徑時,“發現頁面”會自動從 /actuator 移動到管理上下文的根目錄。例如,如果管理上下文路徑是 /management,則發現頁面可從 /management 獲得。當管理上下文路徑設定為 / 時,為防止與其他對映衝突的可能性,發現頁面將被停用。
CORS 支援
跨域資源共享 (CORS) 是一種 W3C 規範,允許您靈活地指定授權的跨域請求型別。如果您使用 Spring MVC 或 Spring WebFlux,您可以配置 Actuator 的 Web 端點以支援此類場景。
預設情況下,CORS 支援是停用的,並且只有在您設定了 management.endpoints.web.cors.allowed-origins 屬性後才啟用。以下配置允許來自 example.com 域的 GET 和 POST 呼叫
-
屬性
-
YAML
management.endpoints.web.cors.allowed-origins=https://example.com
management.endpoints.web.cors.allowed-methods=GET,POST
management:
endpoints:
web:
cors:
allowed-origins: "https://example.com"
allowed-methods: "GET,POST"
有關選項的完整列表,請參閱 CorsEndpointProperties。 |
JSON
使用 JSON 時,Jackson 用於序列化和反序列化。預設情況下,使用一個獨立的 JsonMapper。這種隔離意味著它不與應用程式的 JsonMapper 共享相同的配置,並且不受 spring.jackson.* 屬性的影響。要停用此行為並配置 Actuator 使用應用程式的 JsonMapper,請將 management.endpoints.jackson.isolated-json-mapper 設定為 false。或者,您可以定義自己的 EndpointJsonMapper bean,它生成一個滿足您需求的 JsonMapper。Actuator 將使用它進行 JSON 處理。
實現自定義端點
如果您新增一個用 @Bean 註解並用 @Endpoint 註解的 bean,則所有用 @ReadOperation、@WriteOperation 或 @DeleteOperation 註解的方法將自動透過 JMX 公開,在 Web 應用程式中也透過 HTTP 公開。端點可以透過 Jersey、Spring MVC 或 Spring WebFlux 透過 HTTP 公開。如果 Jersey 和 Spring MVC 都可用,則使用 Spring MVC。
以下示例公開了一個返回自定義物件的讀取操作
-
Java
-
Kotlin
@ReadOperation
public CustomData getData() {
return new CustomData("test", 5);
}
@ReadOperation
fun getData(): CustomData {
return CustomData("test", 5)
}
您還可以透過使用 @JmxEndpoint 或 @WebEndpoint 編寫特定於技術的端點。這些端點僅限於各自的技術。例如,@WebEndpoint 僅透過 HTTP 公開,而不透過 JMX 公開。
您可以使用 @EndpointWebExtension 和 @EndpointJmxExtension 編寫特定於技術的擴充套件。這些註解允許您提供特定於技術的操作來增強現有端點。一個端點最多可以有一個每種型別的擴充套件。
最後,如果您需要訪問特定於 Web 框架的功能,您可以實現 servlet 或 Spring @Controller 和 @RestController 端點,代價是它們不能透過 JMX 或在使用不同 Web 框架時使用。
接收輸入
端點上的操作透過其引數接收輸入。當透過 Web 公開時,這些引數的值從 URL 的查詢引數和 JSON 請求正文獲取。當透過 JMX 公開時,引數對映到 MBean 操作的引數。預設情況下,引數是必需的。可以透過使用 JSpecify 的 @Nullable 註解使其成為可選。Kotlin 空安全也受支援。
您可以將 JSON 請求正文中的每個根屬性對映到端點的引數。考慮以下 JSON 請求正文
{
"name": "test",
"counter": 42
}
您可以使用它來呼叫一個寫入操作,該操作接受 String name 和 int counter 引數,如下例所示
-
Java
-
Kotlin
@WriteOperation
public void updateData(String name, int counter) {
// injects "test" and 42
}
@WriteOperation
fun updateData(name: String?, counter: Int) {
// injects "test" and 42
}
因為端點是技術無關的,所以在方法簽名中只能指定簡單型別。特別是,不支援宣告一個具有 CustomData 型別(定義 name 和 counter 屬性)的單個引數。 |
為了讓輸入對映到操作方法的引數,實現端點的 Java 程式碼應該用 -parameters 編譯。對於 Kotlin 程式碼,請查閱 Spring Framework 參考中的建議。如果您使用 Spring Boot 的 Gradle 外掛或使用 Maven 和 spring-boot-starter-parent,這將自動發生。 |
輸入型別轉換
傳遞給端點操作方法的引數(如果需要)會自動轉換為所需的型別。在呼叫操作方法之前,透過 JMX 或 HTTP 接收的輸入會使用 ApplicationConversionService 例項以及任何使用 @EndpointConverter 註解的 Converter 或 GenericConverter bean 轉換為所需的型別。
自定義 Web 端點
一個 @Endpoint、@WebEndpoint 或 @EndpointWebExtension 上的操作會自動透過 Jersey、Spring MVC 或 Spring WebFlux 透過 HTTP 公開。如果 Jersey 和 Spring MVC 都可用,則使用 Spring MVC。
路徑
謂詞的路徑由端點 ID 和 Web 公開端點的基本路徑決定。預設基本路徑是 /actuator。例如,ID 為 sessions 的端點使用 /actuator/sessions 作為其謂詞中的路徑。
您可以透過用 @Selector 註解一個或多個操作方法引數來進一步自定義路徑。這樣的引數作為路徑變數新增到路徑謂詞中。當呼叫端點操作時,變數的值將傳遞給操作方法。如果您想捕獲所有剩餘的路徑元素,您可以將 @Selector(Match=ALL_REMAINING) 新增到最後一個引數,並使其成為與 String[] 相容的型別。
消耗
對於使用請求正文的 @WriteOperation (HTTP POST),謂詞的 consumes 子句為 application/vnd.spring-boot.actuator.v2+json, application/json。對於所有其他操作,consumes 子句為空。
生成
謂詞的 produces 子句可以透過 @DeleteOperation、@ReadOperation 和 @WriteOperation 註解的 produces 屬性來確定。該屬性是可選的。如果未使用,則 produces 子句將自動確定。
Web 端點響應狀態
端點操作的預設響應狀態取決於操作型別(讀取、寫入或刪除)以及操作是否返回值。
如果 @ReadOperation 返回一個值,則響應狀態將為 200 (OK)。如果它不返回值,則響應狀態將為 404 (Not Found)。
如果 @WriteOperation 或 @DeleteOperation 返回一個值,則響應狀態將為 200 (OK)。如果它不返回值,則響應狀態將為 204 (No Content)。
如果呼叫操作時缺少必需引數或引數無法轉換為所需型別,則不會呼叫操作方法,並且響應狀態將為 400 (Bad Request)。
Web 端點範圍請求
您可以使用 HTTP 範圍請求來請求 HTTP 資源的一部分。當使用 Spring MVC 或 Spring Web Flux 時,返回 Resource 的操作會自動支援範圍請求。
| 使用 Jersey 時不支援範圍請求。 |
Web 端點安全
Web 端點或 Web 特定端點擴充套件上的操作可以接收當前 Principal 或 SecurityContext 作為方法引數。前者通常與 @Nullable 結合使用,為已認證和未認證使用者提供不同的行為。後者通常用於使用其 isUserInRole(String) 方法執行授權檢查。
健康資訊
您可以使用健康資訊來檢查執行中應用程式的狀態。它通常被監控軟體用於在生產系統崩潰時提醒某人。health 端點公開的資訊取決於 management.endpoint.health.show-details 和 management.endpoint.health.show-components 屬性,這些屬性可以配置為以下值之一
| 名稱 | 描述 |
|---|---|
|
從不顯示詳細資訊。 |
|
詳細資訊僅顯示給授權使用者。授權角色可以使用 |
|
詳細資訊顯示給所有使用者。 |
預設值為 never。當用戶屬於端點的一個或多個角色時,該使用者被視為已授權。如果端點沒有配置角色(預設),所有已認證使用者都被視為已授權。您可以使用 management.endpoint.health.roles 屬性配置角色。
如果您已保護您的應用程式並希望使用 always,則您的安全配置必須允許已認證和未經認證的使用者訪問健康端點。 |
健康資訊從 HealthContributorRegistry 的內容收集(預設情況下,您的 ApplicationContext 中定義的所有 HealthContributor 例項)。Spring Boot 包含許多自動配置的 HealthContributor bean,您也可以編寫自己的。
一個 HealthContributor 可以是 HealthIndicator 或 CompositeHealthContributor。HealthIndicator 提供實際的健康資訊,包括一個 Status。CompositeHealthContributor 提供其他 HealthContributor 例項的組合。總而言之,貢獻者形成一個樹形結構來表示整體系統健康狀況。
預設情況下,最終的系統健康狀況由 StatusAggregator 派生,它根據狀態的有序列表對每個 HealthIndicator 的狀態進行排序。排序列表中的第一個狀態用作整體健康狀態。如果沒有 HealthIndicator 返回 StatusAggregator 已知的狀態,則使用 UNKNOWN 狀態。
您可以使用 HealthContributorRegistry 在執行時註冊和登出健康指示器。 |
自動配置的 HealthIndicators
在適當的情況下,Spring Boot 會自動配置下表中列出的 HealthIndicator bean。您還可以透過配置 management.health.key.enabled 來啟用或停用選定的指示器,其中 key 列在下表中
| 鍵 | 名稱 | 描述 |
|---|---|---|
|
檢查 Cassandra 資料庫是否正常執行。 |
|
|
檢查 Couchbase 叢集是否正常執行。 |
|
|
檢查是否可以獲取到 |
|
|
檢查磁碟空間是否不足。 |
|
|
檢查 Elasticsearch 叢集是否正常執行。 |
|
|
檢查 Hazelcast 伺服器是否正常執行。 |
|
|
檢查 JMS 代理是否正常執行。 |
|
|
檢查 LDAP 伺服器是否正常執行。 |
|
|
檢查郵件伺服器是否正常執行。 |
|
|
檢查 Mongo 資料庫是否正常執行。 |
|
|
檢查 Neo4j 資料庫是否正常執行。 |
|
|
始終響應 |
|
|
檢查 Rabbit 伺服器是否正常執行。 |
|
|
檢查 Redis 伺服器是否正常執行。 |
|
|
檢查 SSL 證書是否正常。 |
您可以透過設定 management.health.defaults.enabled 屬性來停用所有這些功能。 |
ssl HealthIndicator 有一個名為 management.health.ssl.certificate-validity-warning-threshold 的“警告閾值”屬性。您可以使用此閾值給自己足夠的時間來輪換即將過期的證書。如果 SSL 證書在此閾值定義的期限內將失效,HealthIndicator 將在其響應的詳細資訊部分中報告此情況,其中 details.validChains.certificates.[*].validity.status 將具有值 WILL_EXPIRE_SOON。 |
預設情況下,還啟用以下 HealthIndicator bean
| 鍵 | 名稱 | 描述 |
|---|---|---|
|
公開“活躍度”應用程式可用性狀態。 |
|
|
公開“就緒度”應用程式可用性狀態。 |
這些可以透過使用 management.endpoint.health.probes.enabled 配置屬性來停用。
編寫自定義 HealthIndicators
要提供自定義健康資訊,您可以註冊實現 HealthIndicator 介面的 Spring bean。您需要提供 health() 方法的實現並返回一個 Health 響應。Health 響應應包含一個狀態,並且可以選擇包含要顯示的其他詳細資訊。以下程式碼顯示了一個示例 HealthIndicator 實現
-
Java
-
Kotlin
import org.springframework.boot.health.contributor.Health;
import org.springframework.boot.health.contributor.HealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class MyHealthIndicator implements HealthIndicator {
@Override
public Health health() {
int errorCode = check();
if (errorCode != 0) {
return Health.down().withDetail("Error Code", errorCode).build();
}
return Health.up().build();
}
private int check() {
// perform some specific health check
return ...
}
}
import org.springframework.boot.health.contributor.Health
import org.springframework.boot.health.contributor.HealthIndicator
import org.springframework.stereotype.Component
@Component
class MyHealthIndicator : HealthIndicator {
override fun health(): Health {
val errorCode = check()
if (errorCode != 0) {
return Health.down().withDetail("Error Code", errorCode).build()
}
return Health.up().build()
}
private fun check(): Int {
// perform some specific health check
return ...
}
}
給定 HealthIndicator 的識別符號是 bean 的名稱,如果存在,則不帶 HealthIndicator 字尾。在前面的示例中,健康資訊在名為 my 的條目中可用。 |
健康指標通常透過 HTTP 呼叫,並且需要在任何連線超時之前響應。對於任何響應時間超過 10 秒的健康指標,Spring Boot 將記錄警告訊息。如果您想配置此閾值,可以使用 management.endpoint.health.logging.slow-indicator-threshold 屬性。 |
除了 Spring Boot 預定義的 Status 型別外,Health 可以返回表示新系統狀態的自定義 Status。在這種情況下,您還需要提供 StatusAggregator 介面的自定義實現,或者您必須使用 management.endpoint.health.status.order 配置屬性來配置預設實現。
例如,假設您的一個 HealthIndicator 實現中使用了程式碼為 FATAL 的新 Status。要配置嚴重性順序,請將以下屬性新增到您的應用程式屬性中
-
屬性
-
YAML
management.endpoint.health.status.order=fatal,down,out-of-service,unknown,up
management:
endpoint:
health:
status:
order: "fatal,down,out-of-service,unknown,up"
響應中的 HTTP 狀態碼反映了整體健康狀態。預設情況下,OUT_OF_SERVICE 和 DOWN 對映到 503。任何未對映的健康狀態,包括 UP,對映到 200。如果您透過 HTTP 訪問健康端點,您可能還需要註冊自定義狀態對映。配置自定義對映會停用 DOWN 和 OUT_OF_SERVICE 的預設對映。如果您想保留預設對映,則必須明確配置它們以及任何自定義對映。例如,以下屬性將 FATAL 對映到 503(服務不可用)並保留 DOWN 和 OUT_OF_SERVICE 的預設對映
-
屬性
-
YAML
management.endpoint.health.status.http-mapping.down=503
management.endpoint.health.status.http-mapping.fatal=503
management.endpoint.health.status.http-mapping.out-of-service=503
management:
endpoint:
health:
status:
http-mapping:
down: 503
fatal: 503
out-of-service: 503
如果您需要更多的控制,您可以定義自己的 HttpCodeStatusMapper bean。 |
下表顯示了內建狀態的預設狀態對映
| 狀態 | 對映 |
|---|---|
|
|
|
|
|
預設情況下沒有對映,因此 HTTP 狀態為 |
|
預設情況下沒有對映,因此 HTTP 狀態為 |
響應式健康指示器
對於響應式應用程式,例如使用 Spring WebFlux 的應用程式,ReactiveHealthContributor 提供了一個非阻塞契約來獲取應用程式健康狀況。與傳統的 HealthContributor 類似,健康資訊從 ReactiveHealthContributorRegistry 的內容收集(預設情況下,您的 ApplicationContext 中定義的所有 HealthContributor 和 ReactiveHealthContributor 例項)。不檢查響應式 API 的常規 HealthContributor 例項在彈性排程器上執行。
在響應式應用程式中,您應該使用 ReactiveHealthContributorRegistry 在執行時註冊和登出健康指示器。如果您需要註冊常規的 HealthContributor,您應該將其包裝在 ReactiveHealthContributor#adapt 中。 |
要從響應式 API 提供自定義健康資訊,您可以註冊實現 ReactiveHealthIndicator 介面的 Spring bean。以下程式碼顯示了一個示例 ReactiveHealthIndicator 實現
-
Java
-
Kotlin
import reactor.core.publisher.Mono;
import org.springframework.boot.health.contributor.Health;
import org.springframework.boot.health.contributor.ReactiveHealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class MyReactiveHealthIndicator implements ReactiveHealthIndicator {
@Override
public Mono<Health> health() {
return doHealthCheck().onErrorResume((exception) ->
Mono.just(new Health.Builder().down(exception).build()));
}
private Mono<Health> doHealthCheck() {
// perform some specific health check
return ...
}
}
import org.springframework.boot.health.contributor.Health
import org.springframework.boot.health.contributor.ReactiveHealthIndicator
import org.springframework.stereotype.Component
import reactor.core.publisher.Mono
@Component
class MyReactiveHealthIndicator : ReactiveHealthIndicator {
override fun health(): Mono<Health> {
return doHealthCheck().onErrorResume { exception: Throwable ->
Mono.just(Health.Builder().down(exception).build())
}
}
private fun doHealthCheck(): Mono<Health> {
// perform some specific health check
return ...
}
}
要自動處理錯誤,請考慮從 AbstractReactiveHealthIndicator 擴充套件。 |
自動配置的響應式健康指標
在適當的情況下,Spring Boot 會自動配置以下 ReactiveHealthIndicator bean
| 鍵 | 名稱 | 描述 |
|---|---|---|
|
檢查 Cassandra 資料庫是否正常執行。 |
|
|
檢查 Couchbase 叢集是否正常執行。 |
|
|
檢查 Elasticsearch 叢集是否正常執行。 |
|
|
檢查 Mongo 資料庫是否正常執行。 |
|
|
檢查 Neo4j 資料庫是否正常執行。 |
|
|
檢查 Redis 伺服器是否正常執行。 |
如有必要,響應式指示器會替換常規指示器。此外,任何未明確處理的 HealthIndicator 都會自動包裝。 |
健康組
有時將健康指示器組織成用於不同目的的組是很有用的。
要建立健康指示器組,可以使用 management.endpoint.health.group.<name> 屬性並指定要 include 或 exclude 的健康指示器 ID 列表。例如,要建立一個只包含資料庫指示器的組,您可以定義如下
-
屬性
-
YAML
management.endpoint.health.group.custom.include=db
management:
endpoint:
health:
group:
custom:
include: "db"
然後您可以透過訪問 localhost:8080/actuator/health/custom 來檢查結果。
類似地,要建立一個從組中排除資料庫指示器幷包含所有其他指示器的組,您可以定義如下
-
屬性
-
YAML
management.endpoint.health.group.custom.exclude=db
management:
endpoint:
health:
group:
custom:
exclude: "db"
預設情況下,如果健康組包含或排除了不存在的健康指示器,則啟動會失敗。要停用此行為,請將 management.endpoint.health.validate-group-membership 設定為 false。
預設情況下,組繼承與系統健康相同的 StatusAggregator 和 HttpCodeStatusMapper 設定。但是,您也可以在每個組的基礎上定義這些。如果需要,您還可以覆蓋 show-details 和 roles 屬性
-
屬性
-
YAML
management.endpoint.health.group.custom.show-details=when-authorized
management.endpoint.health.group.custom.roles=admin
management.endpoint.health.group.custom.status.order=fatal,up
management.endpoint.health.group.custom.status.http-mapping.fatal=500
management.endpoint.health.group.custom.status.http-mapping.out-of-service=500
management:
endpoint:
health:
group:
custom:
show-details: "when-authorized"
roles: "admin"
status:
order: "fatal,up"
http-mapping:
fatal: 500
out-of-service: 500
如果您需要註冊自定義的 StatusAggregator 或 HttpCodeStatusMapper bean 以供組使用,可以使用 @Qualifier("groupname")。 |
健康組還可以包含/排除 CompositeHealthContributor。您還可以只包含/排除 CompositeHealthContributor 的某個元件。這可以透過使用元件的完全限定名稱來完成,如下所示
management.endpoint.health.group.custom.include="test/primary"
management.endpoint.health.group.custom.exclude="test/primary/b"
在上面的示例中,custom 組將包含名為 primary 的 HealthContributor,它是複合 test 的一個元件。這裡,primary 本身是一個複合,名為 b 的 HealthContributor 將從 custom 組中排除。
健康組可以在主埠或管理埠的附加路徑上提供。這在 Kubernetes 等雲環境中非常有用,在這些環境中,通常為了安全目的將 Actuator 端點使用單獨的管理埠。擁有單獨的埠可能會導致不可靠的健康檢查,因為即使健康檢查成功,主應用程式也可能無法正常工作。健康組可以透過以下方式配置附加路徑
management.endpoint.health.group.live.additional-path="server:/healthz"
這將使 live 健康組在主伺服器埠的 /healthz 上可用。字首是強制性的,必須是 server:(表示主伺服器埠)或 management:(表示管理埠,如果已配置)。路徑必須是單個路徑段。
DataSource 健康
DataSource 健康指示器顯示標準資料來源和路由資料來源 bean 的健康狀況。路由資料來源的健康狀況包括其每個目標資料來源的健康狀況。在健康端點的響應中,路由資料來源的每個目標都使用其路由鍵命名。如果您不希望在指示器的輸出中包含路由資料來源,請將 management.health.db.ignore-routing-data-sources 設定為 true。
Kubernetes 探針
部署在 Kubernetes 上的應用程式可以透過容器探針提供其內部狀態資訊。根據您的 Kubernetes 配置,kubelet 會呼叫這些探針並對結果做出反應。
預設情況下,Spring Boot 管理您的應用程式可用性狀態。如果部署在 Kubernetes 環境中,Actuator 會從ApplicationAvailability介面收集“活躍度”和“就緒度”資訊,並將這些資訊用於專門的健康指示器:LivenessStateHealthIndicator和ReadinessStateHealthIndicator。這些指示器顯示在全域性健康端點("/actuator/health")上。它們還透過健康組作為單獨的 HTTP 探針公開:"/actuator/health/liveness"和"/actuator/health/readiness"。
然後,您可以配置 Kubernetes 基礎設施,其中包含以下端點資訊
livenessProbe:
httpGet:
path: "/actuator/health/liveness"
port: <actuator-port>
failureThreshold: ...
periodSeconds: ...
readinessProbe:
httpGet:
path: "/actuator/health/readiness"
port: <actuator-port>
failureThreshold: ...
periodSeconds: ...
<actuator-port> 應設定為 Actuator 端點可用的埠。它可以是主 Web 伺服器埠,也可以是單獨的管理埠(如果已設定 "management.server.port" 屬性)。 |
這些健康組會自動啟用。您可以透過使用 management.endpoint.health.probes.enabled 配置屬性來停用它們。
如果應用程式啟動時間超過配置的活躍度週期,Kubernetes 會提到 "startupProbe" 作為可能的解決方案。一般來說,這裡不一定需要 "startupProbe",因為 "readinessProbe" 會一直失敗,直到所有啟動任務完成。這意味著您的應用程式在準備就緒之前不會接收流量。但是,如果您的應用程式啟動時間很長,請考慮使用 "startupProbe" 以確保 Kubernetes 在應用程式啟動過程中不會終止它。請參閱描述探針在應用程式生命週期中的行為的部分。 |
如果您的 Actuator 端點部署在單獨的管理上下文中,則這些端點不使用與主應用程式相同的 Web 基礎設施(埠、連線池、框架元件)。在這種情況下,即使主應用程式無法正常工作(例如,無法接受新連線),探針檢查也可能成功。因此,最好在主伺服器埠上提供 liveness 和 readiness 健康組。這可以透過設定以下屬性來實現
management.endpoint.health.probes.add-additional-paths=true
這將使 liveness 組在主伺服器埠的 /livez 上可用,而 readiness 組在 /readyz 上可用。路徑可以使用每個組上的 additional-path 屬性進行自定義,詳細資訊請參見健康組。
使用 Kubernetes 探針檢查外部狀態
Actuator 將“活躍度”和“就緒度”探針配置為健康組。這意味著所有健康組功能都適用於它們。例如,您可以配置額外的健康指示器
-
屬性
-
YAML
management.endpoint.health.group.readiness.include=readinessState,customCheck
management:
endpoint:
health:
group:
readiness:
include: "readinessState,customCheck"
預設情況下,Spring Boot 不會向這些組新增其他健康指示器。
“活躍度”探針不應依賴於對外部系統的健康檢查。如果應用程式的活躍度狀態中斷,Kubernetes 會嘗試透過重新啟動應用程式例項來解決該問題。這意味著如果外部系統(例如資料庫、Web API 或外部快取)發生故障,Kubernetes 可能會重新啟動所有應用程式例項並導致級聯故障。
至於“就緒度”探針,檢查外部系統的選擇必須由應用程式開發人員仔細做出。因此,Spring Boot 不會在就緒度探針中包含任何額外的健康檢查。如果應用程式例項的就緒度狀態未就緒,Kubernetes 不會將流量路由到該例項。某些外部系統可能不被應用程式例項共享,在這種情況下,它們可以包含在就緒度探針中。其他外部系統可能對應用程式不重要(應用程式可能具有斷路器和回退),在這種情況下,它們絕對不應該包含在內。不幸的是,所有應用程式例項共享的外部系統很常見,您必須做出判斷:將其包含在就緒度探針中並期望當外部服務關閉時應用程式被停止服務,或者將其排除在外並處理堆疊中更高級別的故障,可能透過在呼叫方中使用斷路器。
如果應用程式的所有例項都未就緒,則具有 type=ClusterIP 或 NodePort 的 Kubernetes Service 不會接受任何傳入連線。沒有 HTTP 錯誤響應(503 等),因為沒有連線。具有 type=LoadBalancer 的服務可能會或可能不會接受連線,具體取決於提供商。具有顯式 ingress 的服務也以取決於實現的方式響應——ingress 服務本身必須決定如何處理來自下游的“連線拒絕”。在負載均衡器和 ingress 的情況下,HTTP 503 很可能發生。 |
此外,如果應用程式使用 Kubernetes 自動擴縮,它可能會對應用程式從負載均衡器中移除做出不同的反應,具體取決於其自動擴縮器配置。
應用程式生命週期和探針狀態
Kubernetes 探針支援的一個重要方面是它與應用程式生命週期的一致性。 AvailabilityState(即應用程式的記憶體內部狀態)與實際探針(即公開該狀態)之間存在顯著差異。根據應用程式生命週期的階段,探針可能不可用。
Spring Boot 在啟動和關閉期間釋出應用程式事件,探針可以監聽此類事件並公開 AvailabilityState 資訊。
下表顯示了在不同階段的 AvailabilityState 和 HTTP 聯結器狀態。
當 Spring Boot 應用程式啟動時
| 啟動階段 | LivenessState | ReadinessState | HTTP 伺服器 | 備註 |
|---|---|---|---|---|
啟動中 |
|
|
未啟動 |
Kubernetes 檢查“活躍度”探針,如果應用程式耗時過長,則重新啟動應用程式。 |
已啟動 |
|
|
拒絕請求 |
應用程式上下文已重新整理。應用程式執行啟動任務,但尚未接收流量。 |
就緒 |
|
|
接受請求 |
啟動任務已完成。應用程式正在接收流量。 |
當 Spring Boot 應用程式關閉時
| 關閉階段 | 活躍度狀態 | 就緒度狀態 | HTTP 伺服器 | 備註 |
|---|---|---|---|---|
執行中 |
|
|
接受請求 |
已請求關閉。 |
優雅關閉 |
|
|
新請求被拒絕 |
如果啟用,優雅關閉會處理正在進行的請求。 |
關閉完成 |
不適用 |
不適用 |
伺服器已關閉 |
應用程式上下文已關閉,應用程式已停止。 |
| 有關 Kubernetes 部署的更多資訊,請參閱 Kubernetes 容器生命週期。 |
應用程式資訊
應用程式資訊公開從您的 ApplicationContext 中定義的所有 InfoContributor bean 收集的各種資訊。Spring Boot 包含許多自動配置的 InfoContributor bean,您也可以編寫自己的。
自動配置的 InfoContributors
在適當的時候,Spring 會自動配置以下 InfoContributor bean
| ID | 名稱 | 描述 | 先決條件 |
|---|---|---|---|
|
公開構建資訊。 |
一個 |
|
|
公開 |
無。 |
|
|
公開 git 資訊。 |
一個 |
|
|
公開 Java 執行時資訊。 |
無。 |
|
|
公開作業系統資訊。 |
無。 |
|
|
公開程序資訊。 |
無。 |
|
|
公開 SSL 證書資訊。 |
已配置 SSL 捆綁包。 |
每個貢獻者是否啟用由其 management.info.<id>.enabled 屬性控制。不同的貢獻者對此屬性有不同的預設值,具體取決於它們的先決條件和它們公開的資訊的性質。
由於沒有先決條件表明它們應該被啟用,env、java、os 和 process 貢獻者預設是停用的。ssl 貢獻者有一個配置 SSL Bundle 的先決條件,但預設是停用的。每個都可以透過將其 management.info.<id>.enabled 屬性設定為 true 來啟用。
build 和 git 資訊貢獻者預設啟用。可以透過將其 management.info.<id>.enabled 屬性設定為 false 來停用它們。或者,要停用所有通常預設啟用的貢獻者,請將 management.info.defaults.enabled 屬性設定為 false。
自定義應用程式資訊
當 env 貢獻者啟用時,您可以透過設定 info.* Spring 屬性來定製 info 端點公開的資料。Environment 鍵下所有 info 的屬性都會自動公開。例如,您可以將以下設定新增到您的 application.properties 檔案中
-
屬性
-
YAML
info.app.encoding=UTF-8
info.app.java.source=17
info.app.java.target=17
info:
app:
encoding: "UTF-8"
java:
source: "17"
target: "17"
|
您也可以在構建時擴充套件 info 屬性,而不是硬編碼這些值。 假設您使用 Maven,您可以將前面的示例改寫為
|
Git 提交資訊
info 端點的另一個有用功能是它能夠在專案構建時釋出有關 git 原始碼儲存庫狀態的資訊。如果 GitProperties bean 可用,您可以使用 info 端點來公開這些屬性。
如果類路徑根目錄中存在 git.properties 檔案,則會自動配置一個 GitProperties bean。有關詳細資訊,請參閱生成 Git 資訊。 |
預設情況下,如果存在,端點會公開 git.branch、git.commit.id 和 git.commit.time 屬性。如果您不希望這些屬性中的任何一個出現在端點響應中,則需要將它們從 git.properties 檔案中排除。如果您想顯示完整的 git 資訊(即 git.properties 的完整內容),請使用 management.info.git.mode 屬性,如下所示
-
屬性
-
YAML
management.info.git.mode=full
management:
info:
git:
mode: "full"
要完全停用 info 端點的 git 提交資訊,請將 management.info.git.enabled 屬性設定為 false,如下所示
-
屬性
-
YAML
management.info.git.enabled=false
management:
info:
git:
enabled: false
構建資訊
如果 BuildProperties bean 可用,info 端點也可以釋出有關您的構建的資訊。如果類路徑中存在 META-INF/build-info.properties 檔案,就會發生這種情況。
| Maven 和 Gradle 外掛都可以生成該檔案。有關更多詳細資訊,請參閱生成構建資訊。 |
Java 資訊
info 端點發布有關您的 Java 執行時環境的資訊,有關更多詳細資訊,請參見 JavaInfo。
作業系統資訊
info 端點發布有關您的作業系統的資訊,有關更多詳細資訊,請參見 OsInfo。
程序資訊
info 端點發布有關您的程序的資訊,有關更多詳細資訊,請參見 ProcessInfo。
編寫自定義 InfoContributors
要提供自定義應用程式資訊,您可以註冊實現 InfoContributor 介面的 Spring bean。
以下示例提供了一個包含單個值的 example 條目
-
Java
-
Kotlin
import java.util.Collections;
import org.springframework.boot.actuate.info.Info;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.stereotype.Component;
@Component
public class MyInfoContributor implements InfoContributor {
@Override
public void contribute(Info.Builder builder) {
builder.withDetail("example", Collections.singletonMap("key", "value"));
}
}
import org.springframework.boot.actuate.info.Info
import org.springframework.boot.actuate.info.InfoContributor
import org.springframework.stereotype.Component
import java.util.Collections
@Component
class MyInfoContributor : InfoContributor {
override fun contribute(builder: Info.Builder) {
builder.withDetail("example", Collections.singletonMap("key", "value"))
}
}
如果您訪問 info 端點,您應該會看到包含以下附加條目的響應
{
"example": {
"key" : "value"
}
}
軟體物料清單 (SBOM)
sbom 端點公開軟體物料清單。CycloneDX SBOMs 可以自動檢測,但也可以手動配置其他格式。
sbom Actuator 端點將公開一個名為“application”的 SBOM,它描述了您的應用程式的內容。
| 要自動在專案構建時生成 CycloneDX SBOM,請參閱生成 CycloneDX SBOM 部分。 |
其他 SBOM 格式
如果您想釋出不同格式的 SBOM,可以使用一些配置屬性。
配置屬性 management.endpoint.sbom.application.location 設定應用程式 SBOM 的位置。例如,將其設定為 classpath:sbom.json 將使用類路徑上 /sbom.json 資源的內容。
CycloneDX、SPDX 和 Syft 格式的 SBOM 的媒體型別會自動檢測。要覆蓋自動檢測的媒體型別,請使用配置屬性 management.endpoint.sbom.application.media-type。
附加 SBOMs
Actuator 端點可以處理多個 SBOM。要新增 SBOM,請使用配置屬性 management.endpoint.sbom.additional,如本例所示
-
屬性
-
YAML
management.endpoint.sbom.additional.system.location=optional:file:/system.spdx.json
management.endpoint.sbom.additional.system.media-type=application/spdx+json
management:
endpoint:
sbom:
additional:
system:
location: "optional:file:/system.spdx.json"
media-type: "application/spdx+json"
這將新增一個名為“system”的 SBOM,它儲存在 /system.spdx.json 中。可以使用 optional: 字首來防止檔案不存在時啟動失敗。