|
此版本仍在开发中,尚未视为稳定版。如需最新稳定版本,请使用 Spring Boot 4.0.4! |
端点
Actuator 端点允许你监控并与你的应用程序进行交互。
Spring Boot 内置了许多端点,并允许你添加自己的端点。
例如,health 端点提供了基本的应用程序健康信息。
您可以控制对每个单独端点的访问,并通过 HTTP 或 JMX 公开端点(使其可远程访问)。
当允许访问某个端点并且该端点已被公开时,该端点即被视为可用。
内置端点仅在可用时才会自动配置。
大多数应用程序选择通过 HTTP 公开端点,此时端点的 ID 会与前缀 /actuator 组合映射到一个 URL。
例如,默认情况下,health 端点会被映射到 /actuator/health。
| 要深入了解 Actuator 的端点及其请求和响应格式,请参阅API 文档。 |
以下与技术无关的端点可用:
| ID | <description> </description> |
|---|---|
|
暴露当前应用程序的审计事件信息。
需要一个 |
|
显示应用程序中所有 Spring Bean 的完整列表。 |
|
暴露可用的缓存。 |
|
显示在配置类和自动配置类上评估的条件,以及它们匹配或不匹配的原因。 |
|
显示所有 |
|
暴露来自 Spring 的 |
|
显示已应用的任何 Flyway 数据库迁移。
需要一个或多个 |
|
显示应用程序的健康信息。 |
|
显示 HTTP 交换信息(默认情况下,显示最近 100 个 HTTP 请求 - 响应交换)。
需要一个 |
|
显示任意的应用程序信息。 |
|
显示 Spring Integration 图形。
需要依赖 |
|
显示并修改应用程序中记录器的配置。 |
|
显示已应用的任何 Liquibase 数据库迁移。
需要一个或多个 |
|
显示当前应用程序的“指标”信息,用于诊断应用程序已记录的指标。 |
|
显示所有 |
|
显示有关 Quartz Scheduler 作业的信息。 受净化处理约束。 |
|
显示您应用程序中的计划任务。 |
|
允许从基于 Spring Session 的会话存储中检索和删除用户会话。 需要一个使用 Spring Session 的基于 Servlet 的 Web 应用程序。 |
|
允许应用程序优雅地关闭。 仅在使用 jar 打包时有效。 默认禁用。 |
|
显示由 |
|
执行线程转储。 |
如果你的应用程序是一个 Web 应用程序(Spring MVC、Spring WebFlux 或 Jersey),你可以使用以下附加端点:
| ID | <description> </description> |
|---|---|
|
返回一个堆转储文件。
在 HotSpot JVM 上,返回一个 |
|
返回日志文件的内容(前提是已设置 |
|
以 Prometheus 服务器可抓取的格式暴露指标。
需要依赖 |
控制对端点的访问
默认情况下,除 shutdown 和 heapdump 之外的所有端点的访问都是不受限制的。
要配置对某个端点的允许访问权限,请使用其 management.endpoint.<id>.access 属性。
以下示例允许对 shutdown 端点进行无限制访问:
-
Properties
-
YAML
management.endpoint.shutdown.access=unrestricted
management:
endpoint:
shutdown:
access: unrestricted
如果你希望采用“选择加入”(opt-in)而非“选择退出”(opt-out)的方式来控制访问权限,请将 management.endpoints.access.default 属性设置为 none,然后使用各个端点的 access 属性来重新启用所需端点的访问权限。
以下示例允许对 loggers 端点进行只读访问,并拒绝所有其他端点的访问:
-
Properties
-
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 属性:
| <property> </property> | 默认 |
|---|---|
|
|
|
|
|
|
|
|
include 属性列出了要暴露的端点 ID。
exclude 属性列出了不应暴露的端点 ID。
exclude 属性优先于 include 属性。
你可以使用端点 ID 列表来配置 include 和 exclude 这两个属性。
例如,若要仅通过 JMX 暴露 health 和 info 端点,请使用以下属性:
-
Properties
-
YAML
management.endpoints.jmx.exposure.include=health,info
management:
endpoints:
jmx:
exposure:
include: "health,info"
* 可用于选择所有端点。
例如,要通过 HTTP 暴露除 env 和 beans 端点之外的所有内容,请使用以下属性:
-
Properties
-
YAML
management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=env,beans
management:
endpoints:
web:
exposure:
include: "*"
exclude: "env,beans"
* 在 YAML 中具有特殊含义,因此如果你想包含(或排除)所有端点,请务必加上引号。 |
| 如果你的应用程序对外公开,我们强烈建议你同时保护你的端点。 |
如果您想实现自己的端点暴露策略,可以注册一个 EndpointFilter Bean。 |
安全
出于安全考虑,默认情况下仅通过 HTTP 暴露 /health 端点。
您可以使用 management.endpoints.web.exposure.include 属性来配置要暴露的端点。
在设置 management.endpoints.web.exposure.include 之前,请确保所暴露的监控端点(actuators)不包含敏感信息,或者通过将其置于防火墙之后,或使用类似 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 文档。
如果你将应用程序部署在防火墙之后,你可能希望所有 Actuator 端点都可以在无需身份验证的情况下被访问。
你可以通过修改 management.endpoints.web.exposure.include 属性来实现这一点,如下所示:
-
Properties
-
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()
}
}
在上述两个示例中,配置仅适用于执行器端点。
由于当存在任何 SecurityFilterChain Bean 时,Spring Boot 的安全配置会完全回退,因此您需要配置一个额外的 SecurityFilterChain Bean,并定义适用于应用程序其余部分的规则。 |
跨站请求伪造保护
由于 Spring Boot 依赖于 Spring Security 的默认配置,CSRF(跨站请求伪造)保护默认是启用的。
这意味着在使用默认安全配置时,需要 POST(如 shutdown 和 loggers 端点)、PUT 或 DELETE 请求的 Actuator 端点会返回 403(禁止访问)错误。
| 我们建议仅在您创建的服务由非浏览器客户端使用时,才完全禁用 CSRF 保护。 |
您可以在Spring Security 参考指南中找到有关 CSRF 保护的更多信息。
配置端点
端点会自动缓存不带任何参数的读取操作的响应。
要配置端点缓存响应的时间长度,请使用其 cache.time-to-live 属性。
以下示例将 beans 端点的缓存生存时间设置为 10 秒:
-
Properties
-
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 端点,如果用户已完成身份验证,并且拥有该端点 roles 属性所配置的角色,则该用户被视为已获得授权。 默认情况下,任何经过身份验证的用户都被视为已获得授权。
对于 JMX 端点,所有用户始终被授权。
以下示例允许具有 admin 角色的所有用户以原始形式查看 /env 端点中的值。
未授权的用户或没有 admin 角色的用户将只能看到经过脱敏处理的值。
-
Properties
-
YAML
management.endpoint.env.show-values=when-authorized
management.endpoint.env.roles=admin
management:
endpoint:
env:
show-values: when-authorized
roles: "admin"
此示例假设未定义任何 SanitizingFunction Bean。 |
执行器 Web 端点的超媒体
添加了一个“发现页面”,其中包含指向所有端点的链接。
默认情况下,“发现页面”可通过 /actuator 访问。
要禁用“发现页面”,请在您的应用程序属性中添加以下属性:
-
Properties
-
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 属性后才会启用。
以下配置允许来自 GET 域的 POST 和 example.com 请求:
-
Properties
-
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 用于序列化和反序列化。
默认情况下,会使用一个隔离的 ObjectMapper。
这种隔离意味着它不与应用程序的 ObjectMapper 共享相同的配置,也不会受到 spring.jackson.* 属性的影响。
要禁用此行为并配置 Actuator 使用应用程序的 ObjectMapper,请将 management.endpoints.jackson.isolated-object-mapper 设置为 false。
或者,您可以定义自己的 EndpointObjectMapper Bean,以生成满足您需求的 ObjectMapper。
随后,Actuator 将使用该 Bean 进行 JSON 处理。
实现自定义端点
如果您添加了一个使用 @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 或 @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
}
由于端点是与技术无关的,因此方法签名中只能指定简单类型。
特别是,不支持声明具有 CustomData 类型的单个参数,该类型定义了 name 和 counter 属性。 |
为了让输入能够映射到操作方法的参数,实现端点的 Java 代码应当使用 -parameters 参数进行编译。
对于 Kotlin 代码,请参阅 Spring Framework 参考文档中的建议。
如果你使用 Spring Boot 的 Gradle 插件,或者使用 Maven 并基于 spring-boot-starter-parent,这一操作将自动完成。 |
输入类型转换
传递给端点操作方法的参数会在必要时自动转换为所需的类型。
在调用操作方法之前,通过 ApplicationConversionService 的实例以及任何使用 @EndpointConverter 限定的 Converter 或 GenericConverter Bean,将通过 JMX 或 HTTP 接收的输入转换为所需的类型。
自定义 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
谓词的 produces 子句可由 @DeleteOperation、@ReadOperation 和 @WriteOperation 注解的 produces 属性确定。
该属性是可选的。
如果未使用该属性,则 produces 子句将自动确定。
Web 端点响应状态
端点操作的默认响应状态取决于操作类型(读取、写入或删除)以及该操作是否返回内容。
如果 @ReadOperation 返回一个值,则响应状态将为 200(OK)。
如果它不返回值,则响应状态将为 404(未找到)。
如果 @WriteOperation 或 @DeleteOperation 返回值,则响应状态将为 200(OK)。
如果它不返回值,则响应状态将为 204(无内容)。
如果调用操作时缺少必需的参数,或提供的参数无法转换为所需类型,则不会调用该操作方法,并且响应状态码将为 400(Bad Request)。
Web 端点范围请求
您可以使用 HTTP 范围请求来请求 HTTP 资源的一部分。
当使用 Spring MVC 或 Spring Web Flux 时,返回 Resource 的操作会自动支持范围请求。
| 使用 Jersey 时不支持范围请求。 |
Web 端点安全
对 Web 端点或特定于 Web 的端点扩展的操作可以将当前的 Principal 或 SecurityContext 作为方法参数接收。
前者通常与 @javax.annotation.Nullable 或 @Nullable 结合使用,以便为已认证和未认证用户提供不同的行为。
后者通常用于通过调用其 isUserInRole(String) 方法来执行授权检查。
健康信息
您可以使用健康信息来检查正在运行的应用程序的状态。
监控软件通常会使用这些信息,在生产系统宕机时发出警报。
health 端点所公开的信息取决于 management.endpoint.health.show-details 和 management.endpoint.health.show-components 属性,这两个属性可配置为以下值之一:
| 姓名 | <description> </description> |
|---|---|
|
详细信息从不显示。 |
|
详细信息仅对已授权用户显示。
可通过使用 |
|
详细信息对所有用户可见。 |
默认值为 never。
当用户属于该端点的一个或多个角色时,即被视为已授权。
如果该端点未配置任何角色(默认情况),则所有经过身份验证的用户都被视为已授权。
你可以通过使用 management.endpoint.health.roles 属性来配置这些角色。
如果你已对应用程序进行了安全保护,并希望使用 always,则你的安全配置必须允许经过身份验证和未经身份验证的用户均可访问健康检查端点。 |
健康信息是从 HealthContributorRegistry 的内容中收集的(默认情况下,收集您在 ApplicationContext 中定义的所有 HealthContributor 实例)。
Spring Boot 包含许多自动配置的 HealthContributor Bean,您也可以编写自己的 Bean。
一个 HealthContributor 可以是一个 HealthIndicator 或一个 CompositeHealthContributor。
一个 HealthIndicator 提供实际的健康信息,包括一个 Status。
一个 CompositeHealthContributor 提供其他 HealthContributor 实例的组合。
综上所述,贡献者形成一个树状结构来表示系统的整体健康状况。
默认情况下,最终的系统健康状况由 StatusAggregator 推导得出,该组件根据有序的状态列表对每个 HealthIndicator 的状态进行排序。
排序列表中的第一个状态将用作整体健康状态。
如果没有 HealthIndicator 返回 StatusAggregator 已知的状态,则将使用 UNKNOWN 状态。
您可以使用 HealthContributorRegistry 在运行时注册和注销健康指示器。 |
自动配置的健康指标(HealthIndicators)
在适当的情况下,Spring Boot 会自动配置下表中列出的 HealthIndicator Bean。
您也可以通过配置 management.health.key.enabled 来启用或禁用选定的指示器,
其中 key 如下表所示:
| 键 | 姓名 | <description> </description> |
|---|---|---|
|
检查 Cassandra 数据库是否已启动。 |
|
|
检查 Couchbase 集群是否已启动。 |
|
|
检查是否可以获取到与 |
|
|
检查磁盘空间是否不足。 |
|
|
检查 Elasticsearch 集群是否已启动。 |
|
|
检查 Hazelcast 服务器是否已启动。 |
|
|
检查 JMS 代理是否已启动。 |
|
|
检查 LDAP 服务器是否处于运行状态。 |
|
|
检查邮件服务器是否正常运行。 |
|
|
检查 MongoDB 数据库是否已启动。 |
|
|
检查 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 可用,但默认未启用:
| 键 | 姓名 | <description> </description> |
|---|---|---|
|
公开“存活状态”(Liveness)应用程序可用性状态。 |
|
|
暴露“就绪”(Readiness)应用程序可用性状态。 |
编写自定义健康指标
要提供自定义健康信息,您可以注册实现 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 的标识符是不带 HealthIndicator 后缀的 Bean 名称(如果存在该后缀)。
在前面的示例中,健康信息可在名为 my 的条目中找到。 |
健康指标通常通过 HTTP 调用,并且需要在任何连接超时之前作出响应。
Spring Boot 会对响应时间超过 10 秒的任何健康指标记录一条警告消息。
如果要配置此阈值,可以使用 management.endpoint.health.logging.slow-indicator-threshold 属性。 |
除了 Spring Boot 预定义的 Status 类型之外,Health 还可以返回一个自定义的 Status,用于表示新的系统状态。
在这种情况下,您还需要提供 StatusAggregator 接口的自定义实现,或者必须通过使用 management.endpoint.health.status.order 配置属性来配置默认实现。
例如,假设您的某个 Status 实现中正在使用一个代码为 FATAL 的新 HealthIndicator。
要配置严重程度顺序,请将以下属性添加到您的应用程序配置文件中:
-
Properties
-
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 的默认映射:
-
Properties
-
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.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 继承。 |
自动配置的响应式健康指示器
在适当的情况下,Spring Boot 会自动配置以下 ReactiveHealthIndicator Bean:
| 键 | 姓名 | <description> </description> |
|---|---|---|
|
检查 Cassandra 数据库是否已启动。 |
|
|
检查 Couchbase 集群是否已启动。 |
|
|
检查 Elasticsearch 集群是否已启动。 |
|
|
检查 MongoDB 数据库是否已启动。 |
|
|
检查 Neo4j 数据库是否已启动。 |
|
|
检查 Redis 服务器是否正在运行。 |
如有必要,响应式指标将替换常规指标。
此外,任何未显式处理的 HealthIndicator 都会自动被包装。 |
健康组
有时将健康指标组织成组会很有用,你可以将这些组用于不同的目的。
要创建一个健康状况指示器组,您可以使用 management.endpoint.health.group.<name> 属性,并指定要include(包含)或exclude(排除)的健康状况指示器 ID 列表。
例如,若要创建一个仅包含数据库相关指示器的组,您可以定义如下内容:
-
Properties
-
YAML
management.endpoint.health.group.custom.include=db
management:
endpoint:
health:
group:
custom:
include: "db"
然后,你可以通过访问 localhost:8080/actuator/health/custom 来检查结果。
同样地,若要创建一个组,该组排除数据库指标并包含所有其他指标,您可以定义如下内容:
-
Properties
-
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 属性:
-
Properties
-
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 运行状况指示器显示标准数据源和路由数据源 Bean 的运行状况。
路由数据源的运行状况包括其每个目标数据源的运行状况。
在运行状况端点的响应中,路由数据源的每个目标都使用其路由键进行命名。
如果您不希望指示器的输出中包含路由数据源,请将 management.health.db.ignore-routing-data-sources 设置为 true。
Kubernetes 探针
部署在 Kubernetes 上的应用程序可以通过容器探针提供其内部状态信息。 根据您的 Kubernetes 配置,kubelet 会调用这些探针并根据结果作出响应。
默认情况下,Spring Boot 会管理您的 应用可用性 状态。
如果部署在 Kubernetes 环境中,执行器(actuator)会从 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> 应设置为 Actuator 端点所在的端口。
如果设置了 "management.server.port" 属性,该端口可以是主 Web 服务器端口,也可以是独立的管理端口。 |
这些健康检查组仅在应用程序运行于 Kubernetes 环境中时自动启用。
您可以通过使用 management.endpoint.health.probes.enabled 配置属性在任意环境中启用它们。
如果应用程序的启动时间超过了配置的存活期(liveness period),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 将“存活”(liveness)和“就绪”(readiness)探针配置为健康检查组(Health Groups)。 这意味着所有健康检查组功能都可用于这些探针。 例如,您可以配置额外的健康指示器(Health Indicators):
-
Properties
-
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 在就绪探针(readiness probe)中不包含任何额外的健康检查。如果应用程序实例的就绪状态为未就绪,Kubernetes 将不会将流量路由到该实例。某些外部系统可能不会被应用程序实例共享,在这种情况下,它们可以包含在就绪探针(readiness probe)中。其他外部系统可能对应用程序并非必不可少(应用程序可以具备断路器和降级机制),在这种情况下,它们肯定不应被包含在内。不幸的是,所有应用程序实例共享的外部系统很常见,你必须做出权衡判断:是将其包含在就绪探针中,并在外部服务宕机时将应用程序从服务中移除;还是将其排除在外,在调用方更高层处理故障,例如使用断路器模式。
如果一个应用的所有实例都处于未就绪状态,那么类型为 type=ClusterIP 或 NodePort 的 Kubernetes Service 将不会接受任何传入连接。
由于没有建立连接,因此不会返回 HTTP 错误响应(例如 503 等)。
类型为 type=LoadBalancer 的服务是否接受连接,则取决于具体的云提供商。
对于配置了显式 ingress 的服务,其响应方式也取决于具体实现——ingress 服务本身需要决定如何处理来自下游的“连接被拒绝”情况。
在使用负载均衡器(LoadBalancer)和 Ingress 的情况下,返回 HTTP 503 错误是很有可能的。 |
此外,如果应用程序使用 Kubernetes 自动扩缩容,根据其自动扩缩器的配置不同,当应用程序被移出负载均衡器时,可能会产生不同的反应。
应用程序生命周期和探针状态
Kubernetes 探针支持的一个重要方面是其与应用程序生命周期的一致性。
AvailabilityState(即应用程序的内存内部状态)与实际探针(用于暴露该状态)之间存在显著差异。
根据应用程序生命周期的不同阶段,探针可能不可用。
Spring Boot 在启动和关闭期间发布 应用程序事件,
探针可以监听这些事件并暴露 AvailabilityState 信息。
下表展示了 AvailabilityState 以及不同阶段下 HTTP 连接器的状态。
当一个 Spring Boot 应用程序启动时:
| 启动阶段 | 存活状态 | 就绪状态 | HTTP 服务器 | 注释 |
|---|---|---|---|---|
开始 |
|
|
未启动 |
Kubernetes 会检查“存活”探针(liveness Probe),如果应用程序响应时间过长,就会将其重启。 |
已启动 |
|
|
拒绝请求 |
应用程序上下文已刷新。应用程序正在执行启动任务,但尚未接收流量。 |
准备就绪 |
|
|
接受请求 |
启动任务已完成。应用程序正在接收流量。 |
当 Spring Boot 应用程序关闭时:
| 关闭阶段 | 存活状态 | 就绪状态 | HTTP 服务器 | 注释 |
|---|---|---|---|---|
运行中 |
|
|
接受请求 |
已请求关闭。 |
优雅关闭 |
|
|
新请求被拒绝 |
如果启用,优雅关闭将处理正在进行中的请求。 HTTP 探针也会停止接受流量,因此可用性状态无法从外部直接获取。 |
关闭完成 |
N/A |
N/A |
服务器已关闭 |
应用程序上下文已关闭,应用程序已关闭。 |
有关 Kubernetes 部署的更多信息,请参阅Kubernetes 容器生命周期。
特别是,其中描述了如何使用 preStop 钩子,在 Kubernetes 终止应用之前,为应用提供足够的时间以优雅地关闭。 |
应用程序信息
应用信息暴露了从您的 InfoContributor 中定义的所有 ApplicationContext Bean 收集的各种信息。
Spring Boot 包含许多自动配置的 InfoContributor Bean,您也可以编写自己的 Bean。
自动配置的信息贡献者
在适当的情况下,Spring 会自动配置以下 InfoContributor Bean:
| ID | 姓名 | <description> </description> | 前置条件 |
|---|---|---|---|
|
暴露构建信息。 |
一个 |
|
|
暴露来自 |
None. |
|
|
暴露 Git 信息。 |
一个 |
|
|
暴露 Java 运行时信息。 |
None. |
|
|
暴露操作系统信息。 |
None. |
|
|
公开进程信息。 |
None. |
|
|
公开 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 端点暴露的数据。
在 info 键下的所有 Environment 属性都会自动暴露。
例如,您可以将以下配置添加到您的 application.properties 文件中:
-
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 属性,如下所示:
-
Properties
-
YAML
management.info.git.mode=full
management:
info:
git:
mode: "full"
要完全禁用 info 端点中的 Git 提交信息,请将 management.info.git.enabled 属性设置为 false,如下所示:
-
Properties
-
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。
SSL 信息
info 端点发布有关您的 SSL 证书的信息(这些证书是通过 SSL 捆绑包 配置的),请参阅 SslInfo 了解更多详情。此端点复用 SslHealthIndicator 的“警告阈值”属性(management.health.ssl.certificate-validity-warning-threshold)。如果 SSL 证书将在该阈值定义的时间跨度内失效,其状态在端点响应的 SSL 部分 中将显示为 WILL_EXPIRE_SOON。
编写自定义 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 端点公开了软件物料清单(Software Bill of Materials)。
CycloneDX 格式的 SBOM 可以自动检测,但也可以手动配置其他格式。
sbom 执行器端点将随后暴露一个名为“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。
额外的 SBOM
执行器端点可以处理多个 SBOM。
要添加 SBOM,请使用配置属性 management.endpoint.sbom.additional,如下例所示:
-
Properties
-
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: 前缀来避免启动失败。