1. 概述
在本教程中,我們將介紹 Spring Boot Actuator。 我們首先將介紹基本內容,然後會詳細討論 Spring Boot 中提供的所有功能。
我們將學習如何在 Spring Boot 和 WebFlux 中使用、配置和擴展此監控工具,充分利用響應式編程模型。
Spring Boot Actuator 自 2014 年 4 月發佈,與第一版 Spring Boot 一起發佈。
從 Spring Boot 2 發佈開始,Actuator 已被重新設計,並添加了許多令人興奮的新端點。
本指南分為三個主要部分:
2. 什麼是執行器 (Actuator)?
本質上,Actuator 為我們的應用程序帶來生產級別的特性。
通過依賴 Actuator,我們可以輕鬆地監控我們的應用程序,收集指標,並瞭解應用程序或數據庫的狀態。
該庫的主要優勢在於,我們可以獲得生產級的工具,而無需自己實現這些功能。
執行器主要暴露——健康狀態、指標、信息、dump、env 等。它使用 HTTP 端點或 JMX bean 允許我們與之交互。
一旦該依賴項已添加到 classpath 中,便有多個端點可供我們使用。 就像大多數 Spring 模塊一樣,我們可以通過多種方式輕鬆配置或擴展它。
2.1. 快速上手
我們需要將 spring-boot-actuator 依賴添加到我們的包管理器中,以啓用 Spring Boot Actuator。
在 Maven 中:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>請注意,無論 Boot 版本如何,此聲明仍然有效,因為版本在 Spring Boot 的物料清單 (BOM) 中指定。
3. Spring Boot Actuator
Spring Boot Actuator 保持其基本意圖,但簡化了其模型,擴展了其功能,並採用了更好的默認設置。
Actuator 保留其核心目的,同時簡化了設計,擴展了功能,並增強了默認設置。
首先,此版本變得與技術無關。它還通過將其與應用程序合併簡化了其安全模型。
在各種更改中,重要的是要注意其中一些是破壞性的。這包括 HTTP 請求和響應,以及 Java API。
最後,最新版本現在支持 CRUD 模型,而不是舊的讀/寫模型。
3.1. 技術支持
Actuator 現在具有技術無關性,與之前的版本不同,後者與特定的框架和 API 綁定。其模型設計具有可插拔和可擴展性,從而在不依賴任何特定框架的情況下實現靈活性。
因此,憑藉這種新的模型,我們可以利用 MVC 和 WebFlux 作為底層 Web 技術。
此外,未來技術可以通過實現適當的適配器進行添加。
最後,JMX 仍然受支持,可以無需任何額外代碼即可暴露端點。
3.2. 重要變更
與前版本不同,Actuator 默認情況下啓用了大部分端點。
因此,默認情況下僅提供 /health 和 /info 兩個端點。
如果我們希望啓用所有端點,可以設置 management.endpoints.web.exposure.include=*。 另一種方法是列出需要啓用的端點。
此外,Actuator 現在與常規 App 安全配置共享,從而大大簡化了安全模型。
因此,如果我們在項目中使用了 Spring Security,則需要調整 Actuator 的安全規則以允許 Actuator 端點。
我們可以添加一個條目來允許 /actuator/**:
@Bean
public SecurityFilterChain securityWebFilterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/actuator/**").permitAll()
.anyRequest().authenticated())
.build();
}我們可以在 官方 Actuator 文檔 中找到更多詳細信息。
此外,所有 Actuator 端點現在默認位於 /actuator 路徑下。
與上一版本相同,我們可以使用新的屬性 management.endpoints.web.base-path 修改此路徑。
3.3. 預定義端點
讓我們來審視可用的端點。其中一些已添加,另一些已刪除,並且還有一些進行了重構:
- /auditevents 列表安全審計相關事件,例如用户登錄/註銷。此外,我們還可以按主體或類型等字段進行過濾。
- /beans 返回我們的 BeanFactory 中所有可用的 Bean。與 /auditevents 不同,它不支持過濾。
- /conditions,以前稱為 /autoconfig,生成關於自動配置的報告。
- /configprops 允許我們檢索所有 @ConfigurationProperties Bean。
- /env 返回當前環境屬性。 此外,我們還可以檢索單個屬性。
- /flyway 提供有關我們的 Flyway 數據庫遷移的詳細信息。
- /health 總結了我們應用程序的健康狀態。
- /heapdump 從我們應用程序使用的 JVM 中構建並返回堆轉儲。
- /info 返回通用信息。 這可能包括自定義數據、構建信息或最新的提交詳情。
- /liquibase 類似於 /flyway,但用於 Liquibase。
- /logfile 返回普通應用程序日誌。
- /loggers 允許我們查詢和修改我們應用程序的日誌級別。
- /metrics 提供我們應用程序的指標信息。 這可能包括通用指標以及自定義指標。
- /prometheus 返回類似於之前的指標,但格式化為與 Prometheus 服務器兼容。
- /scheduledtasks 提供關於我們應用程序中每個計劃任務的詳細信息。
- /sessions 列出我們使用 Spring Session 時 HTTP 會話。
- /shutdown 執行應用程序的優雅關閉。
- /threaddump 導出底層 JVM 的線程信息。
3.4. 用於 Actuator 端點的超媒體資源
Spring Boot 添加了一個發現端點,該端點返回指向所有可用 Actuator 端點的鏈接。這將有助於發現 Actuator 端點及其對應的 URL。
默認情況下,該發現端點可通過 /actuator 端點訪問。
因此,如果向該 URL 發送一個 GET 請求,它將返回各種端點的 Actuator 鏈接:
{
"_links": {
"self": {
"href": "http://localhost:8080/actuator",
"templated": false
},
"features-arg0": {
"href": "http://localhost:8080/actuator/features/{arg0}",
"templated": true
},
"features": {
"href": "http://localhost:8080/actuator/features",
"templated": false
},
"beans": {
"href": "http://localhost:8080/actuator/beans",
"templated": false
},
"caches-cache": {
"href": "http://localhost:8080/actuator/caches/{cache}",
"templated": true
},
// truncated
}如上所示,/actuator 端點報告了所有在 _links 字段下可用的 actuator 端點。
此外,如果配置了自定義管理基礎路徑,則應使用該基礎路徑作為發現 URL。
例如,如果將 management.endpoints.web.base-path 設置為 /mgmt,則應請求 /mgmt 端點以查看鏈接列表。
有趣的是,當管理基礎路徑設置為 / 時,為了防止與其他映射衝突,禁用發現端點。
3.5. 健康指標
與前版本類似,我們可以輕鬆地添加自定義指標。與其它API不同,創建自定義健康端點的抽象層保持不變。但是,ReactiveHealthIndicator 這種新的接口已添加,用於實現反應式健康檢查。
讓我們來看一個簡單的反應式健康檢查示例:
@Component
public class DownstreamServiceHealthIndicator implements ReactiveHealthIndicator {
@Override
public Mono<Health> health() {
return checkDownstreamServiceHealth().onErrorResume(
ex -> Mono.just(new Health.Builder().down(ex).build())
);
}
private Mono<Health> checkDownstreamServiceHealth() {
// we could use WebClient to check health reactively
return Mono.just(new Health.Builder().up().build());
}
}健康指標的一個實用功能是我們可以將其聚合為層次結構的一部分。
因此,遵循之前的示例,我們可以將所有下游服務分組到一個 downstream-services 類別下。只要每個嵌套的 service 可訪問,這個類別就會保持健康。
請查看我們關於健康指標的文章,以獲得更深入的瞭解。
3.6. 健康組
Spring Boot 現在允許將健康指示器組織成 組,從而在所有組中的成員之間應用一致的配置。
例如,我們可以創建一個名為 custom 的健康組,通過在我們的 application.properties 中添加以下內容:
management.endpoint.health.group.custom.include=diskSpace,ping這樣一來,自定義組包含磁盤空間和 ping 健康指示器。
現在,如果調用 /actuator/health 端點,它將向我們提供關於健康組的新 JSON 響應:
{"status":"UP","groups":["custom"]}與健康組合作,我們可以查看幾個健康指標的彙總結果。
在這種情況下,如果向 /actuator/health/custom 發送請求:
{"status":"UP"}然後,我們可以通過配置組以顯示更多詳細信息,使用 application.properties:
management.endpoint.health.group.custom.show-components=always
management.endpoint.health.group.custom.show-details=always現在,如果我們將相同的請求發送到 /actuator/health/custom,我們將看到更多詳細信息:
{
"status": "UP",
"components": {
"diskSpace": {
"status": "UP",
"details": {
"total": 499963170816,
"free": 91300069376,
"threshold": 10485760
}
},
"ping": {
"status": "UP"
}
}
}當然,以下是翻譯後的內容:
還可以僅向授權用户顯示這些詳細信息:
management.endpoint.health.group.custom.show-components=when_authorized
management.endpoint.health.group.custom.show-details=when_authorized我們還可以配置自定義狀態映射。
例如,除了返回 HTTP 200 OK 響應外,還可以返回 207 狀態碼:
management.endpoint.health.group.custom.status.http-mapping.up=207我們正在告訴 Spring Boot,如果 自定義組的狀態是 啓用,則返回一個 207 HTTP 狀態碼。
3.7. Spring Boot 中的指標
在 Spring Boot 中,內部指標已被 Micrometer 支持所取代,因此我們應該預期存在破壞性變更。如果我們的應用程序使用了諸如 GaugeService 或 CounterService 這樣的指標服務,它們將不再可用。
此外,Spring Boot 提供了配置自動化的 MeterRegistry Bean,允許我們直接與 Micrometer 交互以獲取指標。
更重要的是,Micrometer 現在是 Actuator 的依賴項的一部分,只要 Actuator 依賴項在類路徑中,我們就可以放心使用。
此外,/metrics 端點的響應已被完全重新設計。
{
"names": [
"jvm.gc.pause",
"jvm.buffer.memory.used",
"jvm.memory.used",
"jvm.buffer.count",
// ...
]
}我們能看到,指標列表不再包含直接值。要訪問特定的指標值,現在可以導航到所需的指標,例如 /actuator/metrics/jvm.gc.pause,以獲取詳細響應:
{
"name": "jvm.gc.pause",
"measurements": [
{
"statistic": "Count",
"value": 3.0
},
{
"statistic": "TotalTime",
"value": 7.9E7
},
{
"statistic": "Max",
"value": 7.9E7
}
],
"availableTags": [
{
"tag": "cause",
"values": [
"Metadata GC Threshold",
"Allocation Failure"
]
},
{
"tag": "action",
"values": [
"end of minor GC",
"end of major GC"
]
}
]
}現在,指標更加全面,包括不同的值以及一些相關的元數據。
3.8. 自定義 /info 端點
/info 端點保持不變。 如前所述,我們可以使用相應的 Maven 或 Gradle 依賴項添加 Git 詳細信息:
<dependency>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
</dependency>同樣,我們還可以通過使用 Maven 或 Gradle 插件,包含構建信息,包括名稱、組和版本:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>3.9. 創建自定義端點
正如我們之前所指出,我們可以創建自定義端點。但是,Spring Boot 已重新設計了實現這一點的流程,以支持新的、技術中立的範式。
讓我們創建一個 Actuator 端點,用於查詢、啓用和禁用應用程序中的功能標誌:
@Component
@Endpoint(id = "features")
public class FeaturesEndpoint {
private Map<String, Feature> features = new ConcurrentHashMap<>();
@ReadOperation
public Map<String, Feature> features() {
return features;
}
@ReadOperation
public Feature feature(@Selector String name) {
return features.get(name);
}
@WriteOperation
public void configureFeature(@Selector String name, Feature feature) {
features.put(name, feature);
}
@DeleteOperation
public void deleteFeature(@Selector String name) {
features.remove(name);
}
public static class Feature {
private Boolean enabled;
// [...] getters and setters
}
}為了獲取端點,我們需要一個 Bean。 在我們的示例中,我們使用 @Component 來實現。 此外,我們需要使用 @Endpoint 對該 Bean 進行裝飾。
為了獲取端點,我們需要一個 Bean。 在我們的示例中,我們使用 <em >@Component</em> 來實現。 此外,我們需要使用 <em >@Endpoint</em> 對該 Bean 進行裝飾。
端點的路徑由 <em >id</em> 參數的 <em >@Endpoint</em> 決定。 在我們的例子中,它會將請求路由到 <em >/actuator/features</em>。
端點的路徑由 <em >id</em> 參數的 <em >@Endpoint</em> 決定。 在我們的例子中,它會將請求路由到 <em >/actuator/features</em>。
一旦準備就緒,我們就可以使用以下方法定義操作:
- @ReadOperation:它將映射到 HTTP GET。
- @WriteOperation:它將映射到 HTTP POST。
- @DeleteOperation:它將映射到 HTTP DELETE。
當我們以包含先前端點的應用程序運行該應用程序時,Spring Boot 將註冊它。
驗證此操作的一種快速方法是檢查日誌:
[...].WebFluxEndpointHandlerMapping: Mapped "{[/actuator/features/{name}],
methods=[GET],
produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
[...].WebFluxEndpointHandlerMapping : Mapped "{[/actuator/features],
methods=[GET],
produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
[...].WebFluxEndpointHandlerMapping : Mapped "{[/actuator/features/{name}],
methods=[POST],
consumes=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
[...].WebFluxEndpointHandlerMapping : Mapped "{[/actuator/features/{name}],
methods=[DELETE]}"[...]在之前的日誌中,我們可以看到 WebFlux 如何暴露我們的新端點。如果改為使用 MVC,它會簡單地委託該技術,而無需修改任何代碼。
此外,我們還需要注意以下幾點:
- 與 MVC 相比,沒有依賴項。
- 方法中存在的元數據(如 敏感、啓用…)不再存在。但是,我們可以使用 @Endpoint(id = “features”, enableByDefault = false) 啓用或禁用端點。
- 不再需要擴展特定的接口。
- 與舊的讀寫模型不同,現在可以使用 DELETE 操作,並使用 @DeleteOperation。
3.10. 擴展現有端點
假設我們希望確保應用程序的生產實例永遠不會是快照版本。
我們決定通過更改 Actuator 中 /info 端點返回信息的 HTTP 狀態碼來實現這一點。如果我們的應用程序恰好是快照版本,我們將會收到不同的 HTTP 狀態碼。
我們可以輕鬆地使用 @EndpointExtension 註解或其更具體的變體 @EndpointWebExtension 或 @EndpointJmxExtension 來擴展預定義的端點行為。
@Component
@EndpointWebExtension(endpoint = InfoEndpoint.class)
public class InfoWebEndpointExtension {
private InfoEndpoint delegate;
// standard constructor
@ReadOperation
public WebEndpointResponse<Map> info() {
Map<String, Object> info = this.delegate.info();
Integer status = getStatus(info);
return new WebEndpointResponse<>(info, status);
}
private Integer getStatus(Map<String, Object> info) {
// return 5xx if this is a snapshot
return 200;
}
}3.11. 啓用所有端點
為了使用 HTTP 訪問 actuator 端點,我們需要同時啓用並暴露它們。
默認情況下,除了 /shutdown 端點,所有端點均已啓用。 只有 /health 和 /info 端點默認被暴露。
我們需要添加以下配置以暴露所有端點:
management.endpoints.web.exposure.include=*為了明確啓用特定端點(例如 /shutdown),我們使用:
management.endpoint.shutdown.enabled=true為了暴露所有啓用的端點,除了一個(例如,/loggers),我們使用:
management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=loggers3.12. 計劃任務端點
scheduledtasks 端點提供有關應用程序計劃任務的信息,包括其類型、目標和調度信息。
此外,Spring Boot Actuator 暴露了計劃任務的元數據,例如最後執行時間、最後執行狀態和下次執行時間。
我們可以通過向/actuator/scheduledtasks 發送 GET 請求來檢索計劃任務。
$ curl 'http://localhost:8080/actuator/scheduledtasks' -i -X GET以下是翻譯後的內容:
最終響應與以下內容類似:
{
"cron": [
{
"runnable": {
"target": "com.baeldung.actuator.JobConfig.scheduleTaskUsingCronExpression"
},
"expression": "0 15 10 15 * ?",
"nextExecution": {
"time": "2025-01-15T06:45:00.000024100Z"
}
}
],
"fixedDelay": [
{
"runnable": {
"target": "com.baeldung.actuator.JobConfig.scheduleFixedDelayTask"
},
"initialDelay": 0,
"interval": 1000,
"lastExecution": {
"time": "2024-12-18T15:55:35.273062600Z",
"status": "SUCCESS"
},
"nextExecution": {
"time": "2024-12-18T15:55:36.272024100Z"
}
}
],
"fixedRate": [
{
"runnable": {
"target": "com.baeldung.actuator.JobConfig.scheduleFixedRateTask"
},
"initialDelay": 0,
"interval": 1000,
"lastExecution": {
"time": "2024-12-18T15:55:35.162062700Z",
"status": "SUCCESS"
},
"nextExecution": {
"time": "2024-12-18T15:55:36.160024100Z"
}
}
],
"custom": []
}如我們所見,/actuator/scheduledtasks 端點會暴露有關計劃任務的額外信息。
3.13. SBOM 端點
軟件材料清單 (SBOM) 描述了構建軟件工件所使用的所有組件、庫和依賴項。SBOM 在識別和管理軟件應用程序中的安全漏洞方面發揮着至關重要的作用。
要為 Spring Boot 應用程序生成 SBOM,可以使用諸如 CycloneDX、SPDX 和 Syft 等工具。 Spring Boot 3.3.0 內置了對 CycloneDX 的支持,使其成為生成 SBOM 的便捷選擇。
讓我們首先在 pom.xml 的 <plugins> 部分導入 cyclonedx-maven-plugin 插件:
<plugin>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-maven-plugin</artifactId>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>makeAggregateBom</goal>
</goals>
</execution>
</executions>
<configuration>
<projectType>application</projectType>
<outputDirectory>${project.build.outputDirectory}/META-INF/sbom</outputDirectory>
<outputFormat>json</outputFormat>
<outputName>application.cdx</outputName>
</configuration>
</plugin>Spring Boot 通過其父項目自動管理該插件的版本。
現在,我們運行 mvn package 命令。 在 Maven 構建過程中,Spring Boot 藉助 CycloneDX 插件生成 SBOM,並將 SBOM 包含在創建的 JAR 文件中。 如果我們查看 JAR 的內容,將在 META-INF/sbom/application.cdx.json 中找到 SBOM。
我們還可以通過 actuator 暴露 SBOM 。 為此,我們需要啓用 SBOM actuator 端點,該端點默認未啓用:
management.endpoints.web.exposure.include=sbom現在,我們準備運行 Spring Boot 應用程序。啓動完成後,我們可以查詢 SBOM 活動端點:
curl http://localhost:8080/actuator/sbom
{"ids":["application"]}此功能返回所有可用的 SBOM 列表,包括應用程序、JVM、操作系統等。默認情況下,只有一個名為 application 的 SBOM,描述我們的 Spring Boot 應用程序:
curl -i http://localhost:8080/actuator/sbom/application
HTTP/1.1 200
Content-Type: application/vnd.cyclonedx+json
Content-Length: 301209
{
"bomFormat" : "CycloneDX",
"specVersion" : "1.5",
"serialNumber" : "urn:uuid:3842be09-b12e-45ed-8038-babb72a53750",
"version" : 1,
...在這裏,我們可以看到我們應用程序的內容。它包含有關我們應用程序的所有依賴項的信息,包括它們的哈希值和許可證、網站問題跟蹤器 URL 以及更多內容。
3.14. SSL 捆包指標端點
Spring Boot Actuator 3.5.0-M1 引入了 SSL 指標,用於監控 SSL 捆包,從而實現主動的證書管理。
它提供了兩個關鍵指標用於 SSL 證書監控:ssl.chains 和 ssl.chain.expiry。 這些指標允許我們監控證書健康狀況,並設置自動警報以在證書過期之前續訂證書,從而確保服務不中斷。
要配置 Spring Boot 以啓用 SSL 捆包指標,我們需要啓用 SSL/TLS 並配置證書捆包,在 application.properties 或 application.yml 文件中:
spring.ssl.bundle.jks.server.keystore.location=classpath:ssl/baeldung.p12
spring.ssl.bundle.jks.server.keystore.password=password
spring.ssl.bundle.jks.server.keystore.type=PKCS12
server.ssl.bundle=server
server.ssl.enabled=false指標 ssl.chains 統計鏈的數量及其狀態(valid, expired, will-expire-soon, not-yet-valid)。
可以通過向 /actuator/metrics/ssl.chains 發送 GET 請求來檢索 ssl.chains:
$ curl 'https://localhost:8080/actuator/metrics/ssl.chains' -i -X GET
{
"name": "ssl.chains",
"measurements": [
{
"statistic": "VALUE",
"value": 1
}
],
"availableTags": [
{
"tag": "status",
"values": [
"valid",
"not-yet-valid",
"expired",
"will-expire-soon"
]
}
]
}測量字段指示鏈的總數(在本例中是1)。狀態標籤列出了可能的狀態,允許按狀態進行過濾。
例如,調用/actuator/metrics/ssl.chains?tag=status:valid來計數有效鏈的響應如下:
{
"name": "ssl.chains",
"measurements": [
{
"statistic": "VALUE",
"value": 1
}
],
"availableTags": []
}指標 ssl.chain.expiry 跟蹤每個證書鏈到期前的秒數。
我們可以通過向 /actuator/metrics/ssl.chain.expiry 發送 GET 請求來獲取 ssl.chain.expiry:
$ curl 'https://localhost:8080/actuator/metrics/ssl.chain.expiry' -i -X GET
{
"name": "ssl.chain.expiry",
"description": "SSL chain expiry",
"baseUnit": "seconds",
"measurements": [
{
"statistic": "VALUE",
"value": 234819836
}
],
"availableTags": [
{
"tag": "chain",
"values": [
"baeldung"
]
},
{
"tag": "certificate",
"values": [
"6842f024"
]
},
{
"tag": "bundle",
"values": [
"server"
]
}
]
}測量字段顯示到到期時間的秒數(即 234819836 秒,約等於 2717 天)。 鏈、證書和捆綁包等標籤提供上下文,從而允許按特定鏈或捆綁包進行過濾(例如,/actuator/metrics/ssl.chain.expiry?tag=chain:baeldung)。
4. 結論
在本文中,我們討論了 Spring Boot Actuator。我們首先定義了 Actuator 的含義及其對我們的作用。
接下來,我們重點介紹了 Spring Boot Actuator,討論瞭如何使用、調整和擴展它。我們還討論了此次迭代中重要的安全更改。然後,我們討論了流行的端點及其更改。
最後,我們演示瞭如何自定義和擴展 Actuator。