端点

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 的汇总列表。受清洗约束。

env

暴露 Spring 的 ConfigurableEnvironment 中的属性。受清洗约束。

flyway

显示已应用的 Flyway 数据库迁移。需要一个或多个 Flyway bean。

health

显示应用健康信息。

httpexchanges

显示 HTTP 交换信息(默认显示最近的 100 个 HTTP 请求-响应交换)。需要一个 HttpExchangeRepository bean。

info

显示任意的应用信息。

integrationgraph

显示 Spring 集成图。需要依赖 spring-integration-core

loggers

显示并修改应用中日志记录器的配置。

liquibase

显示已应用的 Liquibase 数据库迁移。需要一个或多个 Liquibase bean。

metrics

显示当前应用的“指标”信息,用于诊断应用记录的指标。

mappings

显示所有 @RequestMapping 路径的汇总列表。

quartz

显示关于 Quartz 调度器作业的信息。受清洗约束。

scheduledtasks

显示应用中的计划任务。

sessions

允许从 Spring Session 支持的会话存储中检索和删除用户会话。需要使用 Spring Session 的基于 Servlet 的 Web 应用。

shutdown

允许应用优雅停机。仅在使用 jar 打包时有效。默认禁用。

startup

显示由 ApplicationStartup 收集的启动步骤数据。需要将 SpringApplication 配置为使用 BufferingApplicationStartup

threaddump

执行线程转储。

如果您的应用是 Web 应用(Spring MVC、Spring WebFlux 或 Jersey),您可以使用以下附加端点

ID 描述

heapdump

返回一个堆转储文件。在 HotSpot JVM 上,返回 HPROF 格式文件。在 OpenJ9 JVM 上,返回 PHD 格式文件。

logfile

返回日志文件的内容(如果已设置 logging.file.namelogging.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
无法访问的端点将从应用上下文中完全移除。如果您只想更改端点暴露的技术,请改为使用includeexclude 属性

限制访问

可以使用 management.endpoints.access.max-permitted 属性来限制应用范围的端点访问。此属性优先于默认访问或单个端点的访问级别。将其设置为 none 会使所有端点都无法访问。将其设置为 read-only 则只允许对端点进行读取访问。

对于 @Endpoint@JmxEndpoint@WebEndpoint,读取访问等同于使用 @ReadOperation 注解的端点方法。对于 @ControllerEndpoint@RestControllerEndpoint,读取访问等同于可以处理 GETHEAD 请求的请求映射。对于 @ServletEndpoint,读取访问等同于 GETHEAD 请求。

暴露端点

默认情况下,只有 health 端点通过 HTTP 和 JMX 暴露。由于端点可能包含敏感信息,您应仔细考虑何时暴露它们。

要更改暴露哪些端点,请使用以下特定于技术的 includeexclude 属性

属性 默认值

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 属性。您可以将 includeexclude 属性配置为端点 ID 列表。

例如,要仅通过 JMX 暴露 healthinfo 端点,请使用以下属性

  • Properties

  • YAML

management.endpoints.jmx.exposure.include=health,info
management:
  endpoints:
    jmx:
      exposure:
        include: "health,info"

* 可用于选择所有端点。例如,要通过 HTTP 暴露除 envbeans 端点之外的所有内容,请使用以下属性

  • 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。

安全性

出于安全考虑,默认情况下只有 /health 端点通过 HTTP 暴露。您可以使用 management.endpoints.web.exposure.include 属性配置要暴露的端点。

在设置 management.endpoints.web.exposure.include 之前,请确保暴露的 Actuator 不包含敏感信息,或通过防火墙进行保护,或通过 Spring Security 等进行保护。

如果在 classpath 中存在 Spring Security 且没有其他 SecurityFilterChain bean,则除 /health 外的所有 Actuator 都将由 Spring Boot 自动配置保护。如果您定义自定义的 SecurityFilterChain bean,则 Spring Boot 自动配置将退出,并允许您完全控制 Actuator 访问规则。

如果您希望为 HTTP 端点配置自定义安全性(例如,仅允许具有特定角色的用户访问它们),Spring Boot 提供了一些方便的 RequestMatcher 对象,您可以结合 Spring Security 使用。

典型的 Spring Security 配置可能如下所示

  • Java

  • Kotlin

import org.springframework.boot.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()
	}

}
在上述两个示例中,配置仅适用于 Actuator 端点。由于 Spring Boot 的安全配置在存在任何 SecurityFilterChain bean 时会完全退出,因此您需要配置额外的 SecurityFilterChain bean,其规则适用于应用的其余部分。

跨站请求伪造保护

由于 Spring Boot 依赖于 Spring Security 的默认设置,CSRF 保护默认是开启的。这意味着需要 POST(shutdown 和 loggers 端点)、PUTDELETE 的 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。

Actuator 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 属性后才会启用。以下配置允许来自 example.com 域的 GETPOST 调用

  • 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

实现自定义端点

如果您添加一个使用 @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 nameint 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
	}
因为端点是技术无关的,所以方法签名中只能指定简单类型。特别地,不支持声明具有定义了 namecounter 属性的 CustomData 类型单个参数。
为了让输入能够映射到操作方法的参数,实现端点的 Java 代码应该使用 -parameters 进行编译。对于 Kotlin 代码,请查阅 Spring Framework 参考文档中的建议。如果您使用 Spring Boot 的 Gradle 插件或使用 Maven 和 spring-boot-starter-parent,这将自动发生。

输入类型转换

必要时,传递给端点操作方法的参数会自动转换为所需类型。在调用操作方法之前,通过 JMX 或 HTTP 接收的输入会使用 ApplicationConversionService 的实例以及任何使用 @EndpointConverter 限定的 ConverterGenericConverter bean 转换为所需类型。

定制 Web 端点

@Endpoint@WebEndpoint@EndpointWebExtension 上的操作会通过 Jersey、Spring MVC 或 Spring WebFlux 自动通过 HTTP 公开。如果 Jersey 和 Spring MVC 都可用,则使用 Spring MVC。

Web 端点请求谓词

对于 Web 公开端点上的每个操作,都会自动生成一个请求谓词。

路径

谓词的路径由端点的 ID 和 Web 公开端点的基本路径决定。默认基本路径是 /actuator。例如,ID 为 sessions 的端点在其谓词中使用 /actuator/sessions 作为其路径。

您可以通过使用 @Selector 注解操作方法的一个或多个参数来进一步自定义路径。这样的参数会作为路径变量添加到路径谓词中。在调用端点操作时,该变量的值会传递给操作方法。如果您想捕获所有剩余的路径元素,可以将 @Selector(Match=ALL_REMAINING) 添加到最后一个参数,并使其类型与 String[] 兼容。

HTTP 方法

谓词的 HTTP 方法由操作类型决定,如下表所示:

操作 HTTP 方法

@ReadOperation

GET

@WriteOperation

POST

@DeleteOperation

DELETE

接收(Consumes)

对于使用请求体的 @WriteOperation (HTTP POST),谓词的 consumes 子句是 application/vnd.spring-boot.actuator.v2+json, application/json。对于所有其他操作,consumes 子句为空。

生成(Produces)

谓词的 produces 子句可以由 @DeleteOperation@ReadOperation@WriteOperation 注解的 produces 属性决定。该属性是可选的。如果未使用,produces 子句将自动确定。

如果操作方法返回 voidVoid,则 produces 子句为空。如果操作方法返回 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)。

Web 端点范围请求

您可以使用 HTTP 范围请求来请求 HTTP 资源的一部分。当使用 Spring MVC 或 Spring WebFlux 时,返回 Resource 的操作会自动支持范围请求。

使用 Jersey 时不支持范围请求。

Web 端点安全性

Web 端点或 Web 特定端点扩展上的操作可以接收当前的 PrincipalSecurityContext 作为方法参数。前者通常与 @javax.annotation.Nullable@Nullable 结合使用,以便为已认证和未认证用户提供不同的行为。后者通常用于使用其 isUserInRole(String) 方法执行授权检查。

健康信息

您可以使用健康信息来检查正在运行的应用程序的状态。监控软件通常使用它来在生产系统发生故障时发出警报。health 端点公开的信息取决于 management.endpoint.health.show-detailsmanagement.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 可以是 HealthIndicatorCompositeHealthContributor。一个 HealthIndicator 提供实际的健康信息,包括一个 Status。一个 CompositeHealthContributor 提供其他 HealthContributor 实例的组合。总的来说,贡献者形成一个树状结构来表示整体系统健康状况。

默认情况下,最终的系统健康状况由 StatusAggregator 得出,它根据状态的有序列表对每个 HealthIndicator 的状态进行排序。排序列表中的第一个状态用作总体健康状态。如果没有 HealthIndicator 返回 StatusAggregator 已知的状态,则使用 UNKNOWN 状态。

您可以使用 HealthContributorRegistry 在运行时注册和注销健康指标。

自动配置的 HealthIndicators

在适当的时候,Spring Boot 会自动配置下表中列出的 HealthIndicator bean。您还可以通过配置 management.health.key.enabled(其中 key 列在下表中)来启用或禁用选定的指标:

名称 描述

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

公开应用程序的“活跃度(Liveness)”可用性状态。

readinessstate

ReadinessStateHealthIndicator

公开应用程序的“就绪度(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。要配置严重性顺序,请在您的应用程序属性中添加以下属性:

  • 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_SERVICEDOWN 映射到 503。任何未映射的健康状态,包括 UP,都映射到 200。如果您通过 HTTP 访问健康端点,您可能还需要注册自定义状态映射。配置自定义映射会禁用 DOWNOUT_OF_SERVICE 的默认映射。如果您想保留默认映射,必须明确配置它们,以及任何自定义映射。例如,以下属性将 FATAL 映射到 503(服务不可用),并保留 DOWNOUT_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 中定义的所有 HealthContributorReactiveHealthContributor 实例)。未检查响应式 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 来检查结果。

类似地,要创建一个从组中排除数据库指标并包含所有其他指标的组,可以定义以下配置:

  • Properties

  • YAML

management.endpoint.health.group.custom.exclude=db
management:
  endpoint:
    health:
      group:
        custom:
          exclude: "db"

默认情况下,如果健康组包含或排除不存在的健康指标,启动会失败。要禁用此行为,请将 management.endpoint.health.validate-group-membership 设置为 false

默认情况下,健康组继承与系统健康相同的 StatusAggregatorHttpCodeStatusMapper 设置。但是,您也可以按组定义这些设置。如果需要,您还可以覆盖 show-detailsroles 属性:

  • 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
如果您需要注册用于该组的自定义 StatusAggregatorHttpCodeStatusMapper bean,可以使用 @Qualifier("groupname")

健康组还可以包含/排除一个 CompositeHealthContributor。您还可以仅包含/排除 CompositeHealthContributor 的某个特定组件。这可以通过使用组件的完全限定名来完成,如下所示:

management.endpoint.health.group.custom.include="test/primary"
management.endpoint.health.group.custom.exclude="test/primary/b"

在上面的示例中,custom 组将包含名称为 primaryHealthContributor,它是复合指标 test 的一个组件。这里,primary 本身也是一个复合指标,名称为 bHealthContributor 将被排除在 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 管理您的应用程序可用性(Application Availability)状态。如果部署在 Kubernetes 环境中,Actuator 会从 ApplicationAvailability 接口收集“活跃度(Liveness)”和“就绪度(Readiness)”信息,并在专用的健康指标中使用这些信息:LivenessStateHealthIndicatorReadinessStateHealthIndicator。这些指标会显示在全局健康端点 ("/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)周期,Kubernetes 会提及 "startupProbe" 作为可能的解决方案。一般来说,这里不一定需要 "startupProbe",因为 "readinessProbe" 会在所有启动任务完成之前一直失败。这意味着在应用程序准备就绪之前,不会接收流量。然而,如果您的应用程序启动时间很长,考虑使用 "startupProbe" 来确保 Kubernetes 不会在应用程序启动过程中将其杀死。请参阅描述探针在应用程序生命周期中的行为的部分。

如果您的 Actuator 端点部署在单独的管理上下文中,则这些端点不使用与主应用程序相同的 Web 基础设施(端口、连接池、框架组件)。在这种情况下,即使主应用程序无法正常工作(例如,无法接受新连接),探针检查也可能成功。因此,最好让 livenessreadiness 健康组在主服务器端口上可用。这可以通过设置以下属性来完成:

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 可能会重启所有应用程序实例并造成级联故障。

至于“就绪度(readiness)”探针,检查外部系统的选择必须由应用程序开发人员仔细决定。因此,Spring Boot 不在就绪度探针中包含任何附加的健康检查。如果应用程序实例的就绪度状态未准备好,Kubernetes 不会将流量路由到该实例。某些外部系统可能不是由所有应用程序实例共享的,在这种情况下,它们可以包含在就绪度探针中。其他外部系统可能对应用程序不重要(应用程序可能具有断路器和回退机制),在这种情况下,它们绝对不应包含在内。不幸的是,由所有应用程序实例共享的外部系统很常见,您必须做出判断:将其包含在就绪度探针中,并在外部服务宕机时预期应用程序将退出服务,或者将其排除,并在堆栈的更高层处理故障,也许可以通过在调用方使用断路器来实现。

如果应用程序的所有实例都处于未就绪状态,则具有 type=ClusterIPNodePort 的 Kubernetes Service 不会接受任何传入连接。由于没有连接,因此不会出现 HTTP 错误响应(503 等)。具有 type=LoadBalancer 的 Service 可能会或可能不会接受连接,具体取决于提供商。具有显式ingress 的 Service 的响应方式也取决于实现——ingress 服务本身必须决定如何处理来自下游的“连接被拒绝”。在负载均衡器和 ingress 的情况下,HTTP 503 的可能性很高。

此外,如果应用程序使用 Kubernetes autoscaling(自动伸缩),它对应用程序退出负载均衡器的反应方式可能会因其自动伸缩配置而异。

应用生命周期和探针状态

Kubernetes 探针支持的一个重要方面是它与应用生命周期的一致性。在 AvailabilityState(它是应用的内存内部状态)和实际探针(它暴露了该状态)之间存在显著差异。根据应用生命周期的阶段,探针可能不可用。

Spring Boot 在启动和关闭期间发布应用事件,探针可以监听这些事件并暴露 AvailabilityState 信息。

下表显示了不同阶段的 AvailabilityState 和 HTTP 连接器状态。

Spring Boot 应用启动时

启动阶段 LivenessState(存活状态) ReadinessState(就绪状态) HTTP 服务器 备注

正在启动 (Starting)

BROKEN(损坏)

REFUSING_TRAFFIC(拒绝流量)

未启动

Kubernetes 检查“存活(liveness)”探针,如果耗时过长则重启应用。

已启动 (Started)

CORRECT(正确)

REFUSING_TRAFFIC(拒绝流量)

拒绝请求

应用上下文已刷新。应用执行启动任务,尚未接收流量。

就绪 (Ready)

CORRECT(正确)

ACCEPTING_TRAFFIC(接受流量)

接受请求

启动任务已完成。应用正在接收流量。

Spring Boot 应用关闭时

关闭阶段 存活状态 (Liveness State) 就绪状态 (Readiness State) HTTP 服务器 备注

运行中

CORRECT(正确)

ACCEPTING_TRAFFIC(接受流量)

接受请求

已请求关闭。

优雅关机

CORRECT(正确)

REFUSING_TRAFFIC(拒绝流量)

新请求被拒绝

如果启用,优雅关机处理进行中的请求

关闭完成

不适用

不适用

服务器已关闭

应用上下文已关闭,应用已停止运行。

有关 Kubernetes 部署的更多信息,请参见Kubernetes 容器生命周期

应用信息

应用信息暴露了从 ApplicationContext 中定义的所有 InfoContributor bean 中收集到的各种信息。Spring Boot 包含许多自动配置的 InfoContributor bean,你也可以编写自己的贡献者。

自动配置的 InfoContributor

在适当的情况下,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 属性控制。不同的贡献者对该属性有不同的默认值,具体取决于其前提条件和所暴露信息的性质。

由于没有前提条件表明它们应该被启用,envjavaosprocess 贡献者默认是禁用的。ssl 贡献者需要配置SSL Bundle作为前提条件,但默认也是禁用的。通过将其 management.info.<id>.enabled 属性设置为 true 可以启用它们。

buildgit 信息贡献者默认是启用的。通过将其 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,可以将上述示例重写如下:

  • Properties

  • YAML

info:
  app:
    encoding: "@project.build.sourceEncoding@"
    java:
      source: "@java.version@"
      target: "@java.version@"

Git 提交信息

info 端点的另一个有用功能是它能够发布项目构建时 git 源代码仓库状态的信息。如果 GitProperties bean 可用,你可以使用 info 端点暴露这些属性。

如果在 classpath 的根目录提供了 git.properties 文件,则会自动配置一个 GitProperties bean。更多详细信息请参见生成 Git 信息

默认情况下,如果存在,端点会暴露 git.branchgit.commit.idgit.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 端点也可以发布有关构建的信息。如果 classpath 中存在 META-INF/build-info.properties 文件,就会发生这种情况。

Maven 和 Gradle 插件都可以生成该文件。更多详细信息请参见生成构建信息

Java 信息

info 端点发布有关 Java 运行时环境的信息,更多详细信息请参见 JavaInfo

操作系统信息

info 端点发布有关操作系统的信息,更多详细信息请参见 OsInfo

进程信息

info 端点发布有关进程的信息,更多详细信息请参见 ProcessInfo

SSL 信息

info 端点发布有关 SSL 证书的信息(通过SSL Bundles配置),更多详细信息请参见 SslInfo。此端点重用了 SslHealthIndicator 的“警告阈值”属性:如果 SSL 证书将在该阈值定义的时间范围内失效,它将触发警告。参见 management.health.ssl.certificate-validity-warning-threshold 属性。

编写自定义 InfoContributor

要提供自定义应用信息,你可以注册实现 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 actuator 端点将暴露一个名为“application”的 SBOM,它描述了你的应用内容。

要在项目构建时自动生成 CycloneDX SBOM,请参见生成 CycloneDX SBOM 部分。

其他 SBOM 格式

如果你想发布其他格式的 SBOM,可以使用一些配置属性。

配置属性 management.endpoint.sbom.application.location 设置应用 SBOM 的位置。例如,将其设置为 classpath:sbom.json 将使用 classpath 中 /sbom.json 资源的内容。

CycloneDX、SPDX 和 Syft 格式的 SBOM 的媒体类型会自动检测。要覆盖自动检测的媒体类型,请使用配置属性 management.endpoint.sbom.application.media-type

附加 SBOM

actuator 端点可以处理多个 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: 前缀来防止文件不存在时启动失败。