端点
端点
- 控制端点的访问权限
- 限制访问
- 暴露端点
- 安全性
- 跨站请求伪造保护
- 配置端点
- 清理敏感值
- Actuator Web 端点的超媒体支持
- CORS 支持
- 实现自定义端点
- 接收输入
- 自定义 Web 端点
- 健康信息
- 自动配置的 HealthIndicators
- 编写自定义 HealthIndicators
- 响应式健康指示器
- 自动配置的 ReactiveHealthIndicators
- 健康组
- 数据源健康
- Kubernetes 探针
- 使用 Kubernetes 探针检查外部状态
- 应用程序生命周期和探针状态
- 应用程序信息
- 自动配置的 InfoContributors
- 自定义应用程序信息
- Git 提交信息
- 构建信息
- Java 信息
- 操作系统信息
- 进程信息
- SSL 信息
- 编写自定义 InfoContributors
- 软件物料清单 (SBOM)
- 其他 SBOM 格式
- 额外的 SBOMs
Actuator 端点允许你监控和与你的应用程序进行交互。Spring Boot 包含了许多内置的端点,并且允许你添加自己的端点。例如,health
端点提供了基本的应用程序健康信息。
你可以控制每个单独端点的访问权限,并且通过 HTTP 或 JMX 暴露它们(使其可以远程访问)。当端点的访问被允许并且它被暴露时,该端点才被视为可用。内置端点只有在可用时才会自动配置。大多数应用程序选择通过 HTTP 暴露端点,其中端点的 ID 和 /actuator
前缀会映射到一个 URL。例如,默认情况下,health
端点会映射到 /actuator/health
。
要了解更多关于 Actuator 的端点及其请求和响应格式的信息,请参阅 API 文档。
以下是与技术无关的端点:
ID | 描述 |
---|---|
auditevents | 暴露当前应用程序的审计事件信息。需要配置一个 AuditEventRepository bean。 |
beans | 显示应用程序中所有 Spring bean 的完整列表。 |
caches | 暴露可用的缓存。 |
conditions | 显示在配置和自动配置类上评估的条件,以及它们匹配或不匹配的原因。 |
configprops | 显示所有 @ConfigurationProperties 的整理列表。受 sanitization 约束。 |
env | 暴露 Spring 的 ConfigurableEnvironment 中的属性。受 sanitization 约束。 |
flyway | 显示已应用的 Flyway 数据库迁移。需要配置一个或多个 Flyway bean。 |
health | 显示应用程序的健康信息。 |
httpexchanges | 显示 HTTP 交换信息(默认情况下,显示最后 100 个 HTTP 请求-响应交换)。需要配置一个 HttpExchangeRepository bean。 |
info | 显示任意的应用程序信息。 |
integrationgraph | 显示 Spring Integration 图。需要依赖 spring-integration-core 。 |
loggers | 显示并修改应用程序中日志记录器的配置。 |
liquibase | 显示已应用的 Liquibase 数据库迁移。需要配置一个或多个 Liquibase bean。 |
metrics | 显示当前应用程序的“指标”信息。 |
mappings | 显示所有 @RequestMapping 路径的整理列表。 |
quartz | 显示有关 Quartz Scheduler 作业的信息。受 sanitization 约束。 |
scheduledtasks | 显示应用程序中的计划任务。 |
sessions | 允许从 Spring Session 支持的会话存储中检索和删除用户会话。需要基于 Servlet 的 Web 应用程序并使用 Spring Session。 |
shutdown | 允许优雅地关闭应用程序。仅在 jar 打包时有效。默认禁用。 |
startup | 显示由 ApplicationStartup 收集的 启动步骤数据。需要将 SpringApplication 配置为使用 BufferingApplicationStartup。 |
threaddump | 执行线程转储。 |
如果您的应用程序是一个 Web 应用程序(Spring MVC、Spring WebFlux 或 Jersey),您可以使用以下额外的端点:
ID | 描述 |
---|---|
heapdump | 返回堆转储文件。在 HotSpot JVM 上,返回 HPROF 格式的文件。在 OpenJ9 JVM 上,返回 PHD 格式的文件。 |
logfile | 返回日志文件的内容(如果设置了 logging.file.name 或 logging.file.path 属性)。支持使用 HTTP Range 头来检索日志文件的部分内容。 |
prometheus | 以 Prometheus 服务器可以抓取的格式暴露指标。需要依赖 micrometer-registry-prometheus 。 |
控制对端点的访问
默认情况下,除了 shutdown
之外,所有端点的访问都是不受限制的。要配置对某个端点的允许访问,请使用其 management.endpoint.<id>.access
属性。以下示例允许对 shutdown
端点进行不受限制的访问:
- Properties
- YAML
management.endpoint.shutdown.access=unrestricted
management:
endpoint:
shutdown:
access: unrestricted
如果您希望访问是选择加入而非选择退出,请将 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
请求。
暴露端点
默认情况下,只有健康检查端点通过 HTTP 和 JMX 暴露。由于端点可能包含敏感信息,您应该仔细考虑何时暴露它们。
要更改暴露的端点,请使用以下特定技术的 include
和 exclude
属性:
属性 | 默认值 |
---|---|
management.endpoints.jmx.exposure.exclude | |
management.endpoints.jmx.exposure.include | health |
management.endpoints.web.exposure.exclude | |
management.endpoints.web.exposure.include | health |
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"
*
可以用来选择所有端点。例如,要暴露除 env
和 beans
端点之外的所有内容通过 HTTP 访问,可以使用以下属性:
- 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
之前,请确保暴露的执行器不包含敏感信息,并通过将其放置在防火墙后面或使用类似 Spring Security 的工具来保护它们。
如果类路径中存在 Spring Security 且没有其他 SecurityFilterChain bean,Spring Boot 自动配置会保护除 /health
之外的所有执行器端点。如果你定义了一个自定义的 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()
}
}
在前面的两个示例中,配置仅适用于执行器端点。由于 Spring Boot 的安全配置在存在任何 SecurityFilterChain bean 时会完全回退,因此你需要配置一个额外的 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
以外的值 -
没有应用自定义的 SanitizingFunction Bean
show-values
属性可以为可清理的端点配置为以下值之一:
-
never
- 值总是被完全脱敏(替换为******
) -
always
- 值对所有用户可见(只要没有 SanitizingFunction bean 应用) -
when-authorized
- 值仅对授权用户可见(只要没有 SanitizingFunction bean 应用)
对于 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 支持是禁用的,只有在设置了 management.endpoints.web.cors.allowed-origins
属性后才会启用。以下配置允许来自 example.com
域的 GET
和 POST
调用:
- 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。
实现自定义端点
如果你添加了一个带有 @Bean 注解的组件,并且这个组件上标注了 @Endpoint 注解,那么任何带有 @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。
Web 端点请求谓词
对于 Web 暴露的端点上的每个操作,都会自动生成一个请求谓词(request predicate)。
路径
谓词的路径由端点的 ID 和 web 暴露端点的基本路径决定。默认的基本路径是 /actuator
。例如,ID 为 sessions
的端点使用 /actuator/sessions
作为其在谓词中的路径。
你可以通过使用 @Selector
注解来进一步自定义路径。你可以在操作方法的一个或多个参数上添加 @Selector
注解。这样的参数会作为路径变量添加到路径谓词中。当调用端点操作时,该变量的值会传递给操作方法。如果你想捕获所有剩余的路径元素,可以在最后一个参数上添加 @Selector(Match=ALL_REMAINING)
,并将其类型设置为与 String[]
转换兼容的类型。
HTTP 方法
谓词的 HTTP 方法由操作类型决定,如下表所示:
操作 | HTTP 方法 |
---|---|
@ReadOperation | GET |
@WriteOperation | POST |
@DeleteOperation | DELETE |
消耗者
对于使用请求体的 @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 时不支持范围请求(Range requests)。
Web 端点安全性
在 Web 端点或特定于 Web 的端点扩展上的操作可以接收当前的 Principal 或 SecurityContext 作为方法参数。前者通常与 @javax.annotation.Nullable
或 @Nullable 结合使用,以便为经过身份验证和未经身份验证的用户提供不同的行为。后者通常用于通过其 isUserInRole(String)
方法执行授权检查。
健康信息
你可以使用健康信息来检查正在运行的应用程序的状态。监控软件通常会使用这些信息在生产系统出现故障时发出警报。health
端点暴露的信息取决于 management.endpoint.health.show-details
和 management.endpoint.health.show-components
属性,这些属性可以配置为以下值之一:
名称 | 描述 |
---|---|
never | 详细信息从不显示。 |
when-authorized | 详细信息仅对授权用户显示。授权角色可以通过使用 management.endpoint.health.roles 进行配置。 |
always | 详细信息对所有用户显示。 |
默认值为 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 在运行时注册和注销健康指示器。
自动配置的健康指示器
在适当的情况下,Spring Boot 会自动配置下表中列出的 HealthIndicator bean。你也可以通过配置 management.health.key.enabled
来启用或禁用特定的指示器,其中 key
在下表中列出:
Key | Name | Description |
---|---|---|
cassandra | CassandraDriverHealthIndicator | 检查 Cassandra 数据库是否正常运行。 |
couchbase | CouchbaseHealthIndicator | 检查 Couchbase 集群是否正常运行。 |
db | DataSourceHealthIndicator | 检查是否可以获取到 DataSource 的连接。 |
diskspace | DiskSpaceHealthIndicator | 检查磁盘空间是否不足。 |
elasticsearch | ElasticsearchRestClientHealthIndicator | 检查 Elasticsearch 集群是否正常运行。 |
hazelcast | HazelcastHealthIndicator | 检查 Hazelcast 服务器是否正常运行。 |
jms | JmsHealthIndicator | 检查 JMS 代理是否正常运行。 |
ldap | LdapHealthIndicator | 检查 LDAP 服务器是否正常运行。 |
mail | MailHealthIndicator | 检查邮件服务器是否正常运行。 |
mongo | MongoHealthIndicator | 检查 Mongo 数据库是否正常运行。 |
neo4j | Neo4jHealthIndicator | 检查 Neo4j 数据库是否正常运行。 |
ping | PingHealthIndicator | 始终返回 UP 。 |
rabbit | RabbitHealthIndicator | 检查 Rabbit 服务器是否正常运行。 |
redis | RedisHealthIndicator | 检查 Redis 服务器是否正常运行。 |
ssl | SslHealthIndicator | 检查 SSL 证书是否正常。 |
你可以通过设置 management.health.defaults.enabled
属性来禁用所有健康检查。
ssl
HealthIndicator 有一个名为 management.health.ssl.certificate-validity-warning-threshold
的“警告阈值”属性。如果 SSL 证书在由该阈值定义的时间范围内即将失效,HealthIndicator 会发出警告,但它仍会返回 HTTP 200 以不中断应用程序的运行。你可以使用此阈值来为自己留出足够的时间来轮换即将过期的证书。
额外的 HealthIndicator bean 是可用的,但默认情况下并未启用:
键值 | 名称 | 描述 |
---|---|---|
livenessstate | LivenessStateHealthIndicator | 暴露应用程序的“存活”状态。 |
readinessstate | ReadinessStateHealthIndicator | 暴露应用程序的“就绪”状态。 |
编写自定义健康指示器
为了提供自定义的健康信息,你可以注册实现了 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
配置属性来配置默认实现。
例如,假设在您的某个 HealthIndicator 实现中使用了代码为 FATAL
的新 Status。要配置严重性顺序,请将以下属性添加到您的应用程序配置中:
- 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。
下表显示了内置状态的默认状态映射:
状态 | 映射 |
---|---|
DOWN | SERVICE_UNAVAILABLE (503 ) |
OUT_OF_SERVICE | SERVICE_UNAVAILABLE (503 ) |
UP | 默认无映射,因此 HTTP 状态为 200 |
UNKNOWN | 默认无映射,因此 HTTP 状态为 200 |
响应式健康指标
对于响应式应用程序,例如使用 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。
自动配置的 ReactiveHealthIndicators
在适当的情况下,Spring Boot 会自动配置以下 ReactiveHealthIndicator bean:
键值 | 名称 | 描述 |
---|---|---|
cassandra | CassandraDriverReactiveHealthIndicator | 检查 Cassandra 数据库是否正常运行。 |
couchbase | CouchbaseReactiveHealthIndicator | 检查 Couchbase 集群是否正常运行。 |
elasticsearch | ElasticsearchReactiveHealthIndicator | 检查 Elasticsearch 集群是否正常运行。 |
mongo | MongoReactiveHealthIndicator | 检查 Mongo 数据库是否正常运行。 |
neo4j | Neo4jReactiveHealthIndicator | 检查 Neo4j 数据库是否正常运行。 |
redis | RedisReactiveHealthIndicator | 检查 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](http://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 等云环境中非常有用,在这些环境中,出于安全目的,通常使用单独的管理端口来访问执行器端点。使用单独的端口可能会导致健康检查不可靠,因为即使健康检查成功,主应用程序也可能无法正常工作。可以通过以下方式为健康检查组配置额外的路径:
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 接口收集“存活”和“就绪”信息,并在专用的健康指示器中使用这些信息: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
配置属性在任何环境中启用它们。
如果应用程序启动时间超过配置的存活检查周期,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”探针配置为健康组。这意味着所有健康组功能都可以用于它们。例如,你可以配置额外的健康指示器:
- Properties
- YAML
management.endpoint.health.group.readiness.include=readinessState,customCheck
management:
endpoint:
health:
group:
readiness:
include: "readinessState,customCheck"
默认情况下,Spring Boot 不会向这些组添加其他健康指示器。
“存活”(liveness)探针不应依赖于外部系统的健康检查。如果应用程序的存活状态被破坏,Kubernetes 会尝试通过重启应用程序实例来解决该问题。这意味着如果外部系统(如数据库、Web API 或外部缓存)发生故障,Kubernetes 可能会重启所有应用程序实例,从而导致连锁故障。
至于“就绪”探针,应用程序开发人员必须谨慎选择是否检查外部系统。因此,Spring Boot 不会在就绪探针中包含任何额外的健康检查。如果应用程序实例的就绪状态为未就绪,Kubernetes 不会将流量路由到该实例。某些外部系统可能不会被应用程序实例共享,在这种情况下,它们可以包含在就绪探针中。其他外部系统可能对应用程序来说并不重要(应用程序可能有断路器或回退机制),在这种情况下,它们绝对不应包含在就绪探针中。不幸的是,所有应用程序实例共享的外部系统很常见,你必须做出判断:将其包含在就绪探针中,并期望当外部服务不可用时应用程序被停用,或者将其排除在外,并在堆栈的更高层处理故障,例如在调用者中使用断路器。
如果应用程序的所有实例都未就绪,使用 type=ClusterIP
或 NodePort
的 Kubernetes 服务不会接受任何传入连接。由于没有连接,因此不会返回 HTTP 错误响应(如 503 等)。使用 type=LoadBalancer
的服务可能会或可能不会接受连接,具体取决于提供商。具有明确 ingress 的服务也会根据实现方式做出响应 — ingress 服务本身必须决定如何处理来自下游的“连接被拒绝”情况。在负载均衡器和 ingress 的情况下,返回 HTTP 503 的可能性很大。
此外,如果应用程序使用了 Kubernetes 的 自动扩缩容 功能,它可能会根据自动扩缩容的配置,对负载均衡器中移出应用程序做出不同的反应。
应用生命周期与探针状态
Kubernetes Probes 支持的一个重要方面是其与应用程序生命周期的一致性。AvailabilityState(即应用程序的内存内部状态)与实际的探测(暴露该状态)之间存在显著差异。根据应用程序生命周期的阶段,探测可能不可用。
Spring Boot 在启动和关闭期间会发布应用事件,探针可以监听这些事件并暴露AvailabilityState信息。
以下表格展示了 AvailabilityState 以及不同阶段下 HTTP 连接器的状态。
当一个 Spring Boot 应用启动时:
启动阶段 | 存活状态 | 就绪状态 | HTTP 服务器 | 备注 |
---|---|---|---|---|
启动中 | BROKEN | REFUSING_TRAFFIC | 未启动 | Kubernetes 检查“存活”探针,如果时间过长,则会重启应用。 |
已启动 | CORRECT | REFUSING_TRAFFIC | 拒绝请求 | 应用上下文已刷新。应用正在执行启动任务,尚未接收流量。 |
就绪 | CORRECT | ACCEPTING_TRAFFIC | 接受请求 | 启动任务已完成。应用正在接收流量。 |
当一个 Spring Boot 应用程序关闭时:
关机阶段 | 存活状态 | 就绪状态 | HTTP 服务器 | 说明 |
---|---|---|---|---|
运行中 | CORRECT | ACCEPTING_TRAFFIC | 接受请求 | 已请求关机。 |
优雅关机 | CORRECT | REFUSING_TRAFFIC | 新请求被拒绝 | 如果启用,优雅关机处理进行中的请求。 |
关机完成 | N/A | N/A | 服务器已关闭 | 应用程序上下文已关闭,应用程序已关机。 |
有关 Kubernetes 部署的更多信息,请参阅 Kubernetes 容器生命周期。
应用信息
应用信息暴露了从 ApplicationContext 中定义的所有 InfoContributor Bean 收集到的各种信息。Spring Boot 包含了许多自动配置的 InfoContributor Bean,你也可以编写自己的实现。
自动配置的 InfoContributors
在适当的情况下,Spring 会自动配置以下 InfoContributor Bean:
ID | 名称 | 描述 | 前置条件 |
---|---|---|---|
build | BuildInfoContributor | 暴露构建信息。 | 需要一个 META-INF/build-info.properties 资源。 |
env | EnvironmentInfoContributor | 暴露 Environment 中以 info. 开头的任何属性。 | 无。 |
git | GitInfoContributor | 暴露 Git 信息。 | 需要一个 git.properties 资源。 |
java | JavaInfoContributor | 暴露 Java 运行时信息。 | 无。 |
os | OsInfoContributor | 暴露操作系统信息。 | 无。 |
process | ProcessInfoContributor | 暴露进程信息。 | 无。 |
ssl | SslInfoContributor | 暴露 SSL 证书信息。 | 需要配置一个 SSL Bundle。 |
个体贡献者是否启用由其 management.info.<id>.enabled
属性控制。不同的贡献者对此属性有不同的默认值,这取决于它们的先决条件以及它们所暴露信息的性质。
在没有前提条件表明应该启用它们的情况下,env
、java
、os
和 process
贡献者默认是禁用的。ssl
贡献者的前提条件是配置了 SSL 包,但它默认也是禁用的。每个贡献者都可以通过将其 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"
与其硬编码这些值,你也可以在构建时扩展信息属性。
假设你使用 Maven,你可以将前面的示例重写如下:
- Properties
- YAML
info.app.encoding=@project.build.sourceEncoding@
info.app.java.source=@java.version@
info.app.java.target=@java.version@
info:
app:
encoding: "@project.build.sourceEncoding@"
java:
source: "@java.version@"
target: "@java.version@"
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 的“警告阈值”属性:如果某个 SSL 证书在由该阈值定义的时间范围内将失效,则会触发警告。请参阅 management.health.ssl.certificate-validity-warning-threshold
属性。
编写自定义 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 可以自动检测,但其他格式也可以手动配置。
s bom
执行器端点随后将暴露一个名为 "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
执行器端点可以处理多个 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:
前缀可用于在文件不存在时防止启动失败。