跳到主内容
创建时间: 2026-09-16最后更新: 2026-09-16

项目从第一篇就提供了 /api/v1/health,它证明 Controller 能够接收请求并返回一份业务约定的 JSON。部署平台还需要回答另外两个问题:进程是否仍能自行工作,以及这个实例当前是否应该接收新流量。

Spring Boot Actuator 提供面向运维的端点和健康贡献者模型。本章保留现有业务接口,同时增加 /actuator/health、数据库结构检查以及存活和就绪探针,为后续日志、指标、容器部署与优雅停机建立运行状态边界。

1. 两类健康接口

现有业务接口由项目自己定义:

business-health-response.json
1
{
2
"code": 0,
3
"message": "success",
4
"data": {
5
"status": "UP",
6
"service": "spring"
7
}
8
}

它适合演示业务响应格式,也可以为客户端提供应用定义的服务信息。Actuator 健康端点面向部署平台与运维系统:

actuator-health-response.json
1
{
2
"status": "UP"
3
}

二者职责不同,不需要强行合并:

接口主要调用方契约由谁定义是否聚合基础设施状态
/api/v1/health业务客户端、教学页面当前应用默认不聚合
/actuator/health负载均衡、容器平台、运维系统Spring Boot Actuator可以聚合多个贡献者

运维端点的结构、状态码和暴露策略应该保持稳定,业务接口则可以围绕产品契约演进。不要让容器探针依赖带身份登录、复杂业务查询或频繁变化的响应字段。

2. 添加 Actuator

在 pom.xml 中添加 Actuator Starter:

pom.xml
1
<dependency>
2
<groupId>org.springframework.boot</groupId>
3
<artifactId>spring-boot-starter-actuator</artifactId>
4
</dependency>

Spring Boot 自动配置会根据依赖创建端点、健康聚合器和 Micrometer 基础设施。应用不需要手写一个新的 Actuator Controller。

默认 Web 基础路径是 /actuator。启动应用后访问:

terminal.bash
1
curl -i http://localhost:8080/actuator/health

整体状态为 UP 时通常返回 200 OK;聚合状态为 DOWN 或 OUT_OF_SERVICE 时默认映射为 503 Service Unavailable。探针应该同时判断 HTTP 状态,而不是只在响应文本中搜索 UP。

Actuator 中的端点有「是否启用」和「是否通过 Web 暴露」两层控制。端点存在于 ApplicationContext,不表示它一定能从 HTTP 访问。默认暴露范围比较保守,后面需要其他端点时再显式加入白名单。

3. 健康贡献者

/actuator/health 会聚合容器中的 HealthContributor。其中最常见的直接实现是 HealthIndicator,每个贡献者负责检查一个具体子系统。

项目已经配置 DataSource。当相应健康自动配置条件满足时,Spring Boot 会提供数据库健康贡献者,使用数据源验证数据库连接。访问详情被允许时,可以看到类似组件:

health-components.json
01
{
02
"status": "UP",
03
"components": {
04
"db": {
05
"status": "UP"
06
},
07
"diskSpace": {
08
"status": "UP"
09
}
10
}
11
}

整体状态由各贡献者按照状态聚合规则计算。一个关键依赖为 DOWN 时,整体通常也会变为 DOWN。

健康检查应该满足三个条件:执行快速、有明确超时、不会改变业务数据。不要在每次探针请求中扫描大表、调用没有超时的远程接口,或者执行一次真实写入。

数据库连接正常也不一定表示应用需要的表已经完成迁移。可以为当前项目增加一个很轻量的结构检查,与默认连接检查表达不同含义。

4. 自定义检查

Spring Boot 4 的健康贡献者类型位于 org.springframework.boot.health.contributor。创建一个 Bean,执行能够验证 health_status 表存在的轻量查询:

src/main/java/cn/usehook/spring/health/DatabaseSchemaHealthIndicator.java
01
package cn.usehook.spring.health;
02
03
import org.springframework.boot.health.contributor.Health;
04
import org.springframework.boot.health.contributor.HealthIndicator;
05
import org.springframework.dao.DataAccessException;
06
import org.springframework.jdbc.core.simple.JdbcClient;
07
import org.springframework.stereotype.Component;
08
09
@Component
10
public class DatabaseSchemaHealthIndicator implements HealthIndicator {
11
12
private final JdbcClient jdbcClient;
13
14
public DatabaseSchemaHealthIndicator(JdbcClient jdbcClient) {
15
this.jdbcClient = jdbcClient;
16
}
17
18
@Override
19
public Health health() {
20
try {
21
jdbcClient.sql("select 1 from health_status limit 1")
22
.query(Integer.class)
23
.optional();
24
25
return Health.up()
26
.withDetail("table", "health_status")
27
.build();
28
} catch (DataAccessException exception) {
29
return Health.down(exception).build();
30
}
31
}
32
}

查询在表为空时也能成功完成并返回空 Optional;表不存在、连接中断或数据库拒绝查询时才进入异常分支。health() 把已知数据访问失败转换为健康状态,因为 Actuator 聚合器需要得到一个结果,而不是让请求以普通 Controller 异常结束。

Bean 名为 databaseSchemaHealthIndicator,Actuator 会把 HealthIndicator 后缀去掉,组件 ID 因而是 databaseSchema。可以单独查看该组件:

terminal.bash
1
curl http://localhost:8080/actuator/health/databaseSchema

异常详情可能包含数据库信息,不应该默认公开给匿名调用方。生产环境可以保留服务端日志和内部监控,同时限制 HTTP 响应中详情的可见范围。

5. 存活与就绪

存活状态(Liveness)回答「应用是否处于无法自行恢复、需要重启的状态」。就绪状态(Readiness)回答「应用当前是否可以接收流量」。

availability-states.txt
01
应用正在启动
02
-> Liveness:正常
03
-> Readiness:拒绝流量
04
05
应用启动完成
06
-> Liveness:正常
07
-> Readiness:接收流量
08
09
应用内部不可恢复
10
-> Liveness:失败,平台可以重启实例

显式开启探针端点,并把数据库结构检查加入就绪组:

src/main/resources/application.yaml
1
management:
2
endpoint:
3
health:
4
probes:
5
enabled: true
6
group:
7
readiness:
8
include: "readinessState,databaseSchema"

对应地址为:

terminal.bash
1
curl http://localhost:8080/actuator/health/liveness
2
curl http://localhost:8080/actuator/health/readiness

数据库适合影响就绪状态:数据库暂时不可用时,实例可以先退出流量,等待依赖恢复。不要把数据库、缓存或外部 API 放进存活检查;如果外部依赖整体故障,平台不断重启所有正常应用实例只会造成级联问题。

就绪检查也不是数据库查询的替代品。请求开始后依赖仍可能失败,Repository 和事务代码必须继续正确处理异常。

6. 暴露边界

只暴露确实需要的 Web 端点。把前面的探针配置与暴露规则合并后,management 的完整结构如下,不要在同一 YAML 文件中重复声明两个根 management 键:

src/main/resources/application.yaml
01
management:
02
endpoints:
03
web:
04
exposure:
05
include: "health,info"
06
endpoint:
07
health:
08
show-details: when-authorized
09
probes:
10
enabled: true
11
group:
12
readiness:
13
include: "readinessState,databaseSchema"

include 是白名单,不建议使用 "*" 后再期待网络环境自动保证安全。Spring Security 章节已经允许匿名访问 /actuator/health/**,并要求其余 /actuator/** 端点具有 MONITOR 角色;暴露白名单决定端点是否存在,安全规则决定已存在端点由谁访问,两层不能互相替代。env、configprops、beans、conditions 等端点可能暴露配置结构和应用内部信息,即使有身份校验也只应按实际需要开放。

也可以让管理端点使用独立端口:

src/main/resources/application-prod.yaml
1
management:
2
server:
3
port: 8081

独立端口只改变监听边界,本身不等于认证或网络隔离。部署平台还要明确开放哪一个端口、哪些调用方可以访问,以及防火墙和服务发现怎样路由。

验证时至少覆盖三种状态:正常启动返回 UP、数据库结构不可访问时 Readiness 失败、业务 /api/v1/health 仍保持自己的响应契约。Actuator 解决的是运行管理入口,不取代业务接口。

应用状态能够被平台读取以后,还需要在失败发生时留下可以检索和关联的事件。下一篇继续学习日志级别、参数化日志、结构化输出与请求追踪标识。