Actuator health 端点
一句话定位:Spring Boot Actuator 的
/actuator/health端点自动聚合应用及其依赖组件(数据库、磁盘、Redis 等)的健康状态,以UP或DOWN的简洁语义向外暴露系统是否可用。
定义与作用
在传统 SSM 项目中,运维团队判断应用是否健康通常依赖两种土办法:一是直接访问某个业务接口看是否返回 200;二是登录服务器查看进程是否存在。这两种方式都有明显缺陷:业务接口正常不代表数据库能连,进程存在不代表线程池未耗尽。
Spring Boot Actuator 的 health 端点提供标准化的健康检查协议,它自动检测以下指标:
| 健康指标 | 检测内容 | 默认是否启用 |
|---|---|---|
diskSpace | 磁盘剩余空间是否低于阈值 | 是 |
ping | 应用进程是否存活 | 是 |
dataSource | 数据库连接池是否能获取连接 | 是(类路径存在数据源时) |
redis | Redis 连接是否正常 | 是(类路径存在 Redis 时) |
rabbit | RabbitMQ 连接是否正常 | 是(类路径存在 AMQP 时) |
核心设计:
health端点将所有健康指标汇总为一个顶层状态。只要有一个组件为DOWN,整体状态即为DOWN。这让负载均衡器和监控系统可以统一通过 HTTP 状态码或 JSON 判断应用可用性。
适用位置与常用属性
health 端点由引入 spring-boot-starter-actuator 依赖自动开启,无需任何代码注解。其暴露和控制完全通过 application.yml 配置完成。
常用配置属性
# application.yml
management:
server:
port: 8081 # 管理端口与业务端口分离
endpoints:
web:
exposure:
include: "health,info,metrics" # 暴露哪些端点到 HTTP
exclude: "env,beans" # 排除敏感端点
endpoint:
health:
show-details: when_authorized # 何时显示详情(never / when_authorized / always)
show-components: always # 是否显示各组件独立状态
group:
readiness:
include: "ping,dataSource" # 自定义健康分组(如 k8s 就绪探针)
liveness:
include: "ping"
| 属性 | 说明 | 典型值 |
|---|---|---|
management.server.port | Actuator 独立监听端口 | 8081 |
management.endpoints.web.exposure.include | 暴露的 HTTP 端点列表 | health,info 或 * |
management.endpoint.health.show-details | 健康详情可见策略 | never / when_authorized / always |
management.endpoint.health.show-components | 是否展开各组件状态 | always |
management.endpoint.health.group.*.include | 自定义健康检查分组 | dataSource,redis |
安全提示:生产环境中建议
show-details设为never或when_authorized,避免泄露内部组件信息(如数据库类型、磁盘路径)。
核心原理
Health 端点聚合流程
流程解读:
- 外部监控系统(如 Prometheus、Kubernetes、Nginx)向
/actuator/health发起 GET 请求。 HealthEndpoint从HealthContributorRegistry获取所有注册的健康检查器(包括自动配置的和人自定义的)。- 各检查器并行执行自己的检查逻辑(数据库连接、磁盘空间、Redis 连通性等)。
HealthEndpoint按规则聚合:所有组件为UP则整体UP;任一组件为DOWN则整体DOWN。- 返回 JSON 响应。
show-details和show-components配置决定返回信息的详细程度。
Health 状态层次
完整示例
场景说明
飞翔科技的学生成绩管理系统部署到测试环境后,架构师白歌要求小崔配置健康检查端点,使得监控系统能随时知道 MySQL 数据库是否正常。白歌特别要求:健康端点单独开在 8081 端口,业务端口保持 8080,且生产环境不暴露细节。
操作前:未引入 Actuator
# 操作前:application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/student_db
username: root
password: root
server:
port: 8080
此时项目中没有 spring-boot-starter-actuator 依赖,访问 http://localhost:8080/actuator/health 返回 404:
{
"timestamp": "2024-05-20T11:00:00",
"status": 404,
"error": "Not Found",
"path": "/actuator/health"
}
使用该特性的完整代码
步骤一:在 pom.xml 中引入 Actuator Starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
步骤二:在 application.yml 中配置健康端点:
spring:
datasource:
url: jdbc:mysql://localhost:3306/student_db
username: root
password: root
server:
port: 8080
management:
server:
port: 8081
endpoints:
web:
exposure:
include: "health,info"
endpoint:
health:
show-details: always
show-components: always
注意:
show-details: always仅用于开发/测试环境演示。生产环境应改为when_authorized或never。
业务代码无需任何改动,Actuator 自动检测类路径中的 DataSource 并注册 DataSourceHealthIndicator。
操作后运行结果及分析
启动应用后,控制台输出:
Tomcat started on port(s): 8080 (http)
Tomcat started on port(s): 8081 (http) with management context
访问健康端点:
$ curl http://localhost:8081/actuator/health
返回结果:
{
"status": "UP",
"components": {
"db": {
"status": "UP",
"details": {
"database": "MySQL",
"validationQuery": "SELECT 1"
}
},
"diskSpace": {
"status": "UP",
"details": {
"total": 536870912000,
"free": 128849018880,
"threshold": 10485760,
"exists": true
}
},
"ping": {
"status": "UP"
}
}
}
模拟数据库故障(关闭 MySQL 服务)后再次访问:
{
"status": "DOWN",
"components": {
"db": {
"status": "DOWN",
"details": {
"error": "com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure"
}
},
"diskSpace": {
"status": "UP"
},
"ping": {
"status": "UP"
}
}
}
分析:
management.server.port=8081生效:业务端口与管理端口完全分离,避免管理流量影响业务。DataSourceHealthIndicator自动生效:因类路径存在DataSourceBean,Actuator 自动注册数据库健康检查器。- 状态聚合正确:
db为DOWN时整体状态自动变为DOWN,负载均衡器可据此摘除该实例。 show-components=always生效:每个组件的独立状态一目了然,便于快速定位故障源。
易错场景与面试考点
易错场景一:端点未暴露导致 404
# 错误示范:忘记暴露 health 端点
management:
endpoints:
web:
exposure:
include: "" # 空字符串表示不暴露任何端点
后果:访问 /actuator/health 返回 404。小崔误以为 Actuator 没有引入成功,排查了半小时依赖才发现是配置问题。
正确做法:显式指定暴露列表,或开发环境使用 * 暴露全部(生产严禁)。
management:
endpoints:
web:
exposure:
include: "health,info,metrics"
易错场景二:生产环境泄露敏感健康详情
# 错误示范:生产环境 show-details=always
management:
endpoint:
health:
show-details: always
后果:外部可直接看到数据库类型、磁盘路径、具体错误堆栈等信息,为攻击者提供情报。
正确做法:生产环境设为 never 或 when_authorized,并结合 Spring Security 限制访问来源。
management:
endpoint:
health:
show-details: never
面试考点
Q:/actuator/health 返回的 UP 和 DOWN 是如何聚合的?
Actuator 收集所有
HealthContributor的独立状态,采用"一票否决"策略:只要任一组件为DOWN或OUT_OF_SERVICE,整体状态即为对应的最严重级别。状态优先级从高到低为:DOWN>OUT_OF_SERVICE>UP>UNKNOWN。
Q:为什么建议将 Actuator 端口与业务端口分离?
分离后管理流量(如健康检查、指标拉取)不会挤占业务端口的连接池和线程资源。同时,防火墙可单独对管理端口做访问控制(如仅允许监控服务器 IP 访问),避免敏感端点暴露到公网。
Q:Spring Boot 2.7.x 的 health 端点默认暴露哪些组件?
默认自动探测并启用
ping和diskSpace。如果类路径中存在DataSource则自动启用db,存在 Redis 则启用redis,存在 RabbitMQ 则启用rabbit。开发者也可通过management.health.defaults.enabled统一控制。
Q:如何为 Kubernetes 的 readiness 和 liveness 探针定制 health 分组?
通过
management.endpoint.health.group配置自定义分组。例如 readiness 只包含db和ping,liveness 只包含ping。K8s 分别访问/actuator/health/readiness和/actuator/health/liveness。