端点
Actuator 端点允许你监控和与你的应用程序交互。Spring Boot 包含许多内置端点,并允许你添加你自己的端点。例如,health
端点提供基本的应用程序健康信息。
您可以启用或禁用每个单独的端点,并通过 HTTP 或 JMX 公开它们(使其远程可访问)。当端点同时启用和公开时,则认为该端点可用。内置端点仅在其可用时才会自动配置。大多数应用程序选择通过 HTTP 公开端点,其中端点的 ID 和前缀/actuator
映射到一个 URL。例如,默认情况下,health
端点映射到/actuator/health
。
要了解有关执行器端点及其请求和响应格式的更多信息,请参阅API 文档。 |
以下技术无关的端点可用
ID | 描述 |
---|---|
|
公开当前应用程序的审计事件信息。需要一个 |
|
显示应用程序中所有 Spring bean 的完整列表。 |
|
公开可用的缓存。 |
|
显示在配置和自动配置类上评估的条件以及它们匹配或不匹配的原因。 |
|
显示所有 |
|
公开来自 Spring 的 |
|
显示已应用的任何 Flyway 数据库迁移。需要一个或多个 |
|
显示应用程序运行状况信息。 |
|
显示 HTTP 交换信息(默认情况下,最近 100 个 HTTP 请求-响应交换)。需要一个 |
|
显示任意应用程序信息。 |
|
显示 Spring 集成图。需要依赖于 |
|
显示和修改应用程序中日志记录器的配置。 |
|
显示已应用的任何 Liquibase 数据库迁移。需要一个或多个 |
|
显示当前应用程序的“指标”信息。 |
|
显示所有 |
|
显示有关 Quartz 调度程序作业的信息。受清理影响。 |
|
显示应用程序中的计划任务。 |
|
允许从 Spring Session 支持的会话存储中检索和删除用户会话。需要使用 Spring Session 的基于 servlet 的 Web 应用程序。 |
|
允许优雅地关闭应用程序。仅在使用 jar 包时有效。默认情况下禁用。 |
|
显示 |
|
执行线程转储。 |
如果您的应用程序是 Web 应用程序(Spring MVC、Spring WebFlux 或 Jersey),您可以使用以下附加端点
ID | 描述 |
---|---|
|
返回堆转储文件。在 HotSpot JVM 上,返回 |
|
返回日志文件的内容(如果已设置 |
|
以 Prometheus 服务器可以抓取的格式公开指标。需要依赖于 |
启用端点
默认情况下,除shutdown
之外的所有端点都已启用。要配置端点的启用,请使用其management.endpoint.<id>.enabled
属性。以下示例启用了shutdown
端点
-
属性
-
YAML
management.endpoint.shutdown.enabled=true
management:
endpoint:
shutdown:
enabled: true
如果您希望端点启用采用选择加入而不是选择退出,请将management.endpoints.enabled-by-default
属性设置为false
,并使用各个端点的enabled
属性重新选择加入。以下示例启用info
端点并禁用所有其他端点
-
属性
-
YAML
management.endpoints.enabled-by-default=false
management.endpoint.info.enabled=true
management:
endpoints:
enabled-by-default: false
endpoint:
info:
enabled: true
禁用的端点将完全从应用程序上下文中移除。如果您只想更改公开端点的技术,请改用include 和exclude 属性。 |
公开端点
默认情况下,只有 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 之前,请确保公开的执行器不包含敏感信息,通过将其置于防火墙之后来保护它们,或者通过类似 Spring Security 的内容来保护它们。 |
如果 Spring Security 位于类路径上并且没有其他SecurityFilterChain
bean,则除/health
之外的所有执行器都将通过 Spring Boot 自动配置进行保护。如果您定义自定义SecurityFilterChain
bean,Spring Boot 自动配置将后退,让您完全控制执行器访问规则。
如果您希望为 HTTP 端点配置自定义安全性(例如,只允许具有特定角色的用户访问它们),Spring Boot 提供了一些方便的RequestMatcher
对象,您可以将它们与 Spring Security 结合使用。
典型的 Spring Security 配置可能如下例所示
-
Java
-
Kotlin
import org.springframework.boot.actuate.autoconfigure.security.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) throws Exception {
http.securityMatcher(EndpointRequest.toAnyEndpoint());
http.authorizeHttpRequests((requests) -> requests.anyRequest().hasRole("ENDPOINT_ADMIN"));
http.httpBasic(withDefaults());
return http.build();
}
}
import org.springframework.boot.actuate.autoconfigure.security.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 文档。
如果您在防火墙后部署应用程序,您可能更喜欢所有执行器端点都可以访问而无需身份验证。您可以通过更改management.endpoints.web.exposure.include
属性来实现此目的,如下所示
-
属性
-
YAML
management.endpoints.web.exposure.include=*
management:
endpoints:
web:
exposure:
include: "*"
此外,如果存在 Spring Security,您需要添加允许对端点进行未经身份验证的访问的自定义安全配置,如下例所示
-
Java
-
Kotlin
import org.springframework.boot.actuate.autoconfigure.security.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) throws Exception {
http.securityMatcher(EndpointRequest.toAnyEndpoint());
http.authorizeHttpRequests((requests) -> requests.anyRequest().permitAll());
return http.build();
}
}
import org.springframework.boot.actuate.autoconfigure.security.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()
}
}
在以上两个示例中,配置仅适用于执行器端点。由于 Spring Boot 的安全配置在存在任何SecurityFilterChain bean 时完全回退,因此您需要使用适用于应用程序其余部分的规则配置附加的SecurityFilterChain bean。 |
跨站点请求伪造 (CSRF) 保护
由于 Spring Boot 依赖于 Spring Security 的默认值,因此 CSRF 保护默认情况下处于启用状态。这意味着当使用默认安全配置时,需要POST
(shutdown 和 loggers 端点)、PUT
或DELETE
的执行器端点会收到 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
以外的值 -
不适用任何自定义
SanitizingFunction
bean
可以针对可清理端点将show-values
属性配置为以下值之一:
-
never
- 值始终被完全清理(替换为******
) -
always
- 值显示给所有用户(只要不适用SanitizingFunction
bean) -
when-authorized
- 值仅显示给授权用户(只要不适用SanitizingFunction
bean)
对于 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 。 |
实现自定义端点
如果您添加了一个用@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 操作的参数。参数默认为必需的。可以通过使用@javax.annotation.Nullable
或@org.springframework.lang.Nullable
对其进行注释使其成为可选的。
您可以将 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
}
由于端点与技术无关,因此方法签名中只能指定简单类型。特别是,声明具有定义name 和counter 属性的CustomData 类型的单个参数不受支持。 |
为了将输入映射到操作方法的参数,实现端点的 Java 代码应使用-parameters 编译,实现端点的 Kotlin 代码应使用-java-parameters 编译。如果您使用 Spring Boot 的 Gradle 插件,或者如果您使用 Maven 和spring-boot-starter-parent ,则会自动发生这种情况。 |
自定义 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[]
类型兼容的类型。
HTTP 方法
谓词的 HTTP 方法由操作类型确定,如下表所示
操作 | HTTP 方法 |
---|---|
|
|
|
|
|
|
Consumes
对于使用请求正文的@WriteOperation
(HTTP POST
),谓词的consumes
子句为application/vnd.spring-boot.actuator.v2+json, application/json
。对于所有其他操作,consumes
子句为空。
Produces
谓词的produces
子句可以由@DeleteOperation
、@ReadOperation
和@WriteOperation
注释的produces
属性确定。该属性是可选的。如果未使用它,则会自动确定produces
子句。
如果操作方法返回void
或Void
,则produces
子句为空。如果操作方法返回org.springframework.core.io.Resource
,则produces
子句为application/octet-stream
。对于所有其他操作,produces
子句为application/vnd.spring-boot.actuator.v2+json, application/json
。
Web 端点响应状态
端点操作的默认响应状态取决于操作类型(读取、写入或删除)以及操作返回的内容(如果有)。
如果@ReadOperation
返回值,则响应状态将为 200 (OK)。如果它不返回值,则响应状态将为 404 (Not Found)。
如果@WriteOperation
或@DeleteOperation
返回值,则响应状态将为 200 (OK)。如果它不返回值,则响应状态将为 204 (No Content)。
如果在没有必需参数或参数无法转换为所需类型的情况下调用操作,则不会调用操作方法,并且响应状态将为 400 (Bad Request)。
健康信息
您可以使用健康信息来检查正在运行的应用程序的状态。监控软件经常使用它来在生产系统宕机时提醒某人。health
端点公开的信息取决于management.endpoint.health.show-details
和management.endpoint.health.show-components
属性,这些属性可以使用以下值之一进行配置
名称 | 描述 |
---|---|
|
从不显示详细信息。 |
|
仅向授权用户显示详细信息。可以使用 |
|
向所有用户显示详细信息。 |
默认值为never
。当用户属于端点的一个或多个角色时,则认为该用户已获授权。如果端点没有配置的角色(默认情况下),则所有已认证的用户都被认为已获授权。您可以使用management.endpoint.health.roles
属性配置角色。
如果您已保护您的应用程序并希望使用always ,则您的安全配置必须允许已认证和未认证的用户访问健康端点。 |
健康信息是从HealthContributorRegistry
的内容中收集的(默认情况下,是ApplicationContext
中定义的所有HealthContributor
实例)。Spring Boot 包含许多自动配置的HealthContributors
,您也可以编写自己的HealthContributors
。
HealthContributor
可以是HealthIndicator
或CompositeHealthContributor
。HealthIndicator
提供实际的健康信息,包括Status
。CompositeHealthContributor
提供其他HealthContributors
的组合。总而言之,贡献者形成树状结构以表示整体系统健康状况。
默认情况下,最终系统健康状况由StatusAggregator
得出,它根据状态的有序列表对每个HealthIndicator
的状态进行排序。排序列表中的第一个状态用作整体健康状态。如果没有任何HealthIndicator
返回StatusAggregator
已知的status,则使用UNKNOWN
状态。
您可以使用HealthContributorRegistry 在运行时注册和注销健康指标。 |
自动配置的HealthIndicators
在适当的情况下,Spring Boot 会自动配置下表中列出的HealthIndicators
。您也可以通过配置management.health.key.enabled
来启用或禁用选定的指标,其中key
列在下表中。
键 | 名称 | 描述 |
---|---|---|
|
检查 Cassandra 数据库是否启动。 |
|
|
检查 Couchbase 集群是否启动。 |
|
|
检查是否可以获得与 |
|
|
检查磁盘空间是否不足。 |
|
|
检查 Elasticsearch 集群是否启动。 |
|
|
检查 Hazelcast 服务器是否启动。 |
|
|
检查 InfluxDB 服务器是否启动。 |
|
|
检查 JMS 代理是否启动。 |
|
|
检查 LDAP 服务器是否启动。 |
|
|
检查邮件服务器是否启动。 |
|
|
检查 Mongo 数据库是否启动。 |
|
|
检查 Neo4j 数据库是否启动。 |
|
|
始终返回 |
|
|
检查 Rabbit 服务器是否启动。 |
|
|
检查 Redis 服务器是否启动。 |
您可以通过设置management.health.defaults.enabled 属性来禁用所有这些指标。 |
还有其他HealthIndicators
可用,但默认情况下未启用。
键 | 名称 | 描述 |
---|---|---|
|
公开“Liveness”(存活性)应用程序可用性状态。 |
|
|
公开“Readiness”(就绪性)应用程序可用性状态。 |
编写自定义 HealthIndicators
要提供自定义健康信息,您可以注册实现HealthIndicator
接口的 Spring bean。您需要提供health()
方法的实现并返回Health
响应。Health
响应应包含状态,并且可以选择包含要显示的其他详细信息。以下代码显示了一个示例HealthIndicator
实现。
-
Java
-
Kotlin
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.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.actuate.health.Health
import org.springframework.boot.actuate.health.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
的默认映射。如果您想保留默认映射,则必须在任何自定义映射 alongside 旁边显式配置它们。例如,以下属性将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 的常规HealthContributors
在弹性调度程序上执行。
在反应式应用程序中,您应该使用ReactiveHealthContributorRegistry 在运行时注册和注销健康指标。如果您需要注册常规HealthContributor ,则应使用ReactiveHealthContributor#adapt 将其包装。 |
要从反应式 API 提供自定义健康信息,您可以注册实现ReactiveHealthIndicator
接口的 Spring bean。以下代码显示了一个示例ReactiveHealthIndicator
实现。
-
Java
-
Kotlin
import reactor.core.publisher.Mono;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.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.actuate.health.Health
import org.springframework.boot.actuate.health.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 扩展。 |
自动配置的 ReactiveHealthIndicators
在适当的情况下,Spring Boot 会自动配置以下ReactiveHealthIndicators
。
键 | 名称 | 描述 |
---|---|---|
|
检查 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 等云环境中非常有用,在这些环境中,出于安全目的,为执行器端点使用单独的管理端口非常常见。拥有单独的端口可能会导致健康检查不可靠,因为即使健康检查成功,主应用程序也可能无法正常工作。健康组可以配置附加路径如下:
management.endpoint.health.group.live.additional-path="server:/healthz"
这将使live
健康组在主服务器端口上的/healthz
上可用。前缀是必需的,必须是server:
(表示主服务器端口)或management:
(表示管理端口,如果已配置)。路径必须是单个路径段。
Kubernetes 探针
部署在 Kubernetes 上的应用程序可以使用容器探针提供有关其内部状态的信息。根据您的 Kubernetes 配置,kubelet 会调用这些探针并对结果做出反应。
默认情况下,Spring Boot 管理您的应用程序可用性状态。如果部署在 Kubernetes 环境中,执行器会从ApplicationAvailability
接口收集“Liveness”和“Readiness”信息,并在专用健康指标中使用这些信息: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> 应设置为执行器端点可用的端口。如果已设置"management.server.port" 属性,则它可能是主 Web 服务器端口或单独的管理端口。 |
只有当应用程序在 Kubernetes 环境中运行时,才会自动启用这些健康组。您可以使用management.endpoint.health.probes.enabled
配置属性在任何环境中启用它们。
如果应用程序启动时间长于配置的存活性周期,Kubernetes 会将"startupProbe" 列为可能的解决方案。一般来说,这里不一定需要"startupProbe" ,因为"readinessProbe" 会在完成所有启动任务之前失败。这意味着您的应用程序只有在准备好后才会接收流量。但是,如果您的应用程序启动时间很长,请考虑使用"startupProbe" 以确保 Kubernetes 不会在应用程序启动过程中将其终止。请参阅描述探针在应用程序生命周期中的行为的部分。 |
如果您的执行器端点部署在单独的管理上下文中,则这些端点不使用与主应用程序相同的 Web 基础设施(端口、连接池、框架组件)。在这种情况下,即使主应用程序无法正常工作(例如,它无法接受新的连接),探测检查也可能成功。因此,最好在主服务器端口上提供liveness
和readiness
健康组。这可以通过设置以下属性来实现。
management.endpoint.health.probes.add-additional-paths=true
这将使liveness
组在主服务器端口上的/livez
处可用,使readiness
组在/readyz
处可用。路径可以使用每个组上的additional-path
属性进行自定义,详情请参见健康组。
使用 Kubernetes 探针检查外部状态
执行器将“liveness”和“readiness”探针配置为健康组。这意味着所有健康组功能都可用于它们。例如,您可以配置额外的健康指标。
-
属性
-
YAML
management.endpoint.health.group.readiness.include=readinessState,customCheck
management:
endpoint:
health:
group:
readiness:
include: "readinessState,customCheck"
默认情况下,Spring Boot 不会向这些组添加其他健康指标。
“liveness”探针不应依赖于外部系统的健康检查。如果应用程序的存活性状态中断,Kubernetes 会尝试通过重新启动应用程序实例来解决该问题。这意味着如果外部系统(例如数据库、Web API 或外部缓存)发生故障,Kubernetes 可能会重新启动所有应用程序实例并造成级联故障。
至于“readiness”探针,检查外部系统的选择必须由应用程序开发人员仔细做出。因此,Spring Boot 在就绪探针中不包含任何额外的健康检查。如果应用程序实例的就绪状态未就绪,Kubernetes 不会将流量路由到该实例。某些外部系统可能不被应用程序实例共享,在这种情况下,它们可以包含在就绪探针中。其他外部系统可能对应用程序不是必需的(应用程序可能有断路器和回退),在这种情况下,它们绝对不应该包含在内。不幸的是,所有应用程序实例共享的外部系统很常见,您必须做出判断:将其包含在就绪探针中并预期在外部服务关闭时应用程序将被停止服务,或者将其排除在外并处理堆栈上方的故障,也许可以通过在调用方使用断路器。
如果应用程序的所有实例均未就绪,则type=ClusterIP 或NodePort 的 Kubernetes 服务不接受任何传入连接。没有 HTTP 错误响应(503 等),因为没有连接。具有type=LoadBalancer 的服务可能会或可能不会接受连接,具体取决于提供商。具有显式入口的服务的响应方式也取决于实现——入口服务本身必须决定如何处理下游的“连接被拒绝”。对于负载均衡器和入口,HTTP 503 非常有可能。 |
此外,如果应用程序使用 Kubernetes 自动缩放,它可能会根据其自动缩放器配置对应用程序被从负载均衡器中移除做出不同的反应。
应用程序生命周期和探针状态
Kubernetes 探针支持的一个重要方面是其与应用程序生命周期的兼容性。AvailabilityState
(这是应用程序的内存中内部状态)与实际探针(公开该状态)之间存在显著差异。根据应用程序生命周期的阶段,探针可能不可用。
Spring Boot 在启动和关闭期间发布应用程序事件,探针可以监听此类事件并公开AvailabilityState
信息。
下表显示了不同阶段的AvailabilityState
和 HTTP 连接器的状态。
当 Spring Boot 应用程序启动时
启动阶段 | LivenessState | ReadinessState | HTTP 服务器 | 备注 |
---|---|---|---|---|
启动中 |
|
|
未启动 |
Kubernetes 检查“liveness”探针,如果花费时间过长则重新启动应用程序。 |
已启动 |
|
|
拒绝请求 |
应用程序上下文已刷新。应用程序执行启动任务,但尚未接收流量。 |
就绪 |
|
|
接受请求 |
启动任务已完成。应用程序正在接收流量。 |
当 Spring Boot 应用程序关闭时
关闭阶段 | Liveness 状态 | Readiness 状态 | HTTP 服务器 | 备注 |
---|---|---|---|---|
运行中 |
|
|
接受请求 |
已请求关闭。 |
优雅关闭 |
|
|
拒绝新的请求 |
如果启用,优雅关闭会处理进行中的请求。 |
关闭完成 |
N/A |
N/A |
服务器已关闭 |
应用程序上下文已关闭,应用程序已关闭。 |
有关 Kubernetes 部署的更多信息,请参见Kubernetes 容器生命周期。 |
应用程序信息
应用程序信息公开从ApplicationContext
中定义的所有InfoContributor
bean 收集的各种信息。Spring Boot 包含许多自动配置的InfoContributor
bean,您可以编写自己的 bean。
自动配置的 InfoContributors
在适当的情况下,Spring 会自动配置以下InfoContributor
bean
ID | 名称 | 描述 | 前提条件 |
---|---|---|---|
|
公开构建信息。 |
一个 |
|
|
公开 |
无。 |
|
|
公开 git 信息。 |
一个 |
|
|
公开 Java 运行时信息。 |
无。 |
|
|
公开操作系统信息。 |
无。 |
|
|
公开进程信息。 |
无。 |
各个贡献者是否启用由其management.info.<id>.enabled
属性控制。不同的贡献者对此属性具有不同的默认值,具体取决于它们的前提条件以及它们公开的信息的性质。
由于没有前提条件表明它们应该启用,因此env
、java
、os
和process
贡献者默认情况下是禁用的。可以通过将其management.info.<id>.enabled
属性设置为true
来启用每个贡献者。
build
和git
信息贡献者默认情况下是启用的。可以通过将其management.info.<id>.enabled
属性设置为false
来禁用每个贡献者。或者,要禁用通常默认启用的每个贡献者,请将management.info.defaults.enabled
属性设置为false
。
自定义应用程序信息
启用env
贡献者后,您可以通过设置info.*
Spring 属性来自定义info
端点公开的数据。info
键下的所有Environment
属性都会自动公开。例如,您可以将以下设置添加到您的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"
您可以在构建时扩展信息属性,而不是硬编码这些值。 假设您使用 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 SBOM 可以自动检测,但也可以手动配置其他格式。
sbom
执行器端点将公开一个名为“application”的 SBOM,该 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
。
其他 SBOM
执行器端点可以处理多个 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:
前缀防止启动失败。