健康检查与指标
本教程共 48 篇 · 第 37 篇 · 更新于 2026-08-13 · 约 5 分钟阅读
本节目标:看懂 health 端点,会写自定义健康指示器,掌握 Micrometer 指标埋点,并把指标接到 Prometheus。
health 端点:应用活着吗
/actuator/health 返回整体状态:
{"status": "UP"}
状态有四级:UP(正常)、DOWN(挂了)、OUT_OF_SERVICE(主动下线)、UNKNOWN(未知)。
默认只显示总状态。想看细节:
management:
endpoint:
health:
show-details: when-authorized
show-details 三档:never(默认)、when-authorized(登录可见)、always。
Warning新手常在这里栽跟头:配置了
show-details: always,调用却看不到 details。如果应用套了 Spring Security,health 端点默认是匿名可访问的,但always会暴露内部细节,建议用when-authorized。
健康指示器
health 的状态是多个「健康指示器」汇总的结果。Spring Boot 自动配置了一批,按需启用:
| Key | 检查内容 |
|---|---|
db | 数据源能否拿到连接 |
diskspace | 磁盘空间是否充足 |
ping | 总是 UP,验证探活链路 |
redis | Redis 是否可连 |
mongo | MongoDB 是否可连 |
mail | 邮件服务器 |
ssl | SSL 证书是否快过期 |
汇总规则:所有指示器里最差的等级就是整体状态。排序由 StatusAggregator 决定,默认顺序 DOWN 最严重。HTTP 状态码也跟着映射:DOWN 和 OUT_OF_SERVICE 返回 503,UP 返回 200。想自定义映射:
management:
endpoint:
health:
status:
http-mapping:
down: 503
out-of-service: 503
自定义指示器:实现 HealthIndicator 接口。注意 Spring Boot 4 的包名:
package com.example.demo.health;
import org.springframework.boot.health.contributor.Health;
import org.springframework.boot.health.contributor.HealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class DiskHealthIndicator implements HealthIndicator {
@Override
public Health health() {
long free = checkFreeSpace();
if (free < 1024L * 1024 * 1024) {
return Health.down().withDetail("freeBytes", free).build();
}
return Health.up().withDetail("freeBytes", free).build();
}
private long checkFreeSpace() {
return 8L * 1024 * 1024 * 1024; // 示例:实际用 File 检查
}
}
Bean 名去掉 HealthIndicator 后缀就是它在响应里的 key:disk。
Note版本对照:Boot 3.x 的
org.springframework.boot.actuate.health.Health在 4.x 移到了org.springframework.boot.health.contributor包。旧 import 会编译报错。
Tip健康检查要在超时前返回。Spring Boot 会给超过 10 秒的指示器打警告日志,阈值可用
management.endpoint.health.logging.slow-indicator-threshold调整。
健康组与 Kubernetes 探针
健康指示器可以分组。比如「只看数据库」:
management:
endpoint:
health:
group:
db-only:
include: "db"
访问 /actuator/health/db-only 只看这组。健康组默认继承全局的 show-details 和角色配置,也可以单独覆盖,比如 management.endpoint.health.group.db-only.show-details=always。
Kubernetes 部署时,探针直接映射到两个内置健康组:
/actuator/health/liveness:存活探针/actuator/health/readiness:就绪探针
management:
endpoint:
health:
probes:
add-additional-paths: true
加上这行后,主端口额外暴露 /livez 和 /readyz,K8s 探针直接指过去。
liveness 探针别挂外部依赖检查:数据库挂了不该重启应用,该摘流量的是 readiness。这是 K8s 探针设计的核心原则,面试常问。
Micrometer 指标
指标是数字化的健康。Spring Boot 用 Micrometer 收集,统一门面,可对接十几个监控系统。
先看有哪些指标:
curl http://localhost:8080/actuator/metrics
内置指标按前缀分:
jvm.*:内存、GC、线程、类加载system.*/process.*:CPU、文件描述符、运行时长http.server.requests:HTTP 请求数、耗时、状态码分布
下钻查询:
curl "http://localhost:8080/actuator/metrics/jvm.memory.used?tag=area:heap"
Note查询用的名字要和代码里的指标名一致。
jvm.memory.used在 Prometheus 里显示为jvm_memory_used(下划线命名),但查 actuator 时仍写点号。
自定义指标
注入 MeterRegistry,业务代码里埋点。三种基本计量:
Counter:只增不减,适合计数Timer:记录耗时分布,适合接口耗时Gauge:可增可减的当前值,适合队列长度
package com.example.demo.service;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Service;
@Service
public class OrderService {
private final Counter orderCounter;
public OrderService(MeterRegistry registry) {
this.orderCounter = registry.counter("shop.orders.created", "channel", "web");
}
public void createOrder() {
// 业务逻辑
orderCounter.increment();
}
}
registry.counter("名字", "标签名", "标签值") 创建计数器。指标名用点分段,标签用 tag=KEY:VALUE 下钻。
接口耗时用 Timer:
Timer orderTimer = registry.timer("shop.order.processing");
orderTimer.record(() -> {
// 业务逻辑
});
Timer 自带耗时分布统计,接 Prometheus 后能算 P95、P99。队列长度这类当前值用 Gauge。
Tip全局公共标签(环境、机房)用配置统一加:
management.metrics.tags.region=cn-east-1,所有指标自动带上。
埋点注意标签基数:用户 ID、订单号这类高基数标签会撑爆指标系统,别往指标里塞。
对接 Prometheus
Prometheus 是拉模式的监控系统。三步对接:
- 加依赖:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
- 暴露端点:
management:
endpoints:
web:
exposure:
include: "health,prometheus"
- Prometheus 配置抓取任务:
scrape_configs:
- job_name: "spring-boot-app"
metrics_path: "/actuator/prometheus"
static_configs:
- targets: ["localhost:8080"]
Prometheus 定期来抓 /actuator/prometheus,拿到 jvm_*、http_server_requests_* 等指标,配上 Grafana 就能画监控大盘。
Note加了
micrometer-registry-prometheus后,/actuator/prometheus端点才存在,别忘记在 exposure 里放行。
想关掉某个指标,用management.metrics.enable.<前缀>=false。想给特定接口算 P99,用management.metrics.distribution.percentiles-histogram.http.server.requests=true。
从指标到告警
指标接进 Prometheus 只是第一步,配上告警才有意义。
Prometheus 的告警规则文件里写条件,比如「5 分钟内错误率超过 5%」:
groups:
- name: spring-boot-app
rules:
- alert: HighErrorRate
expr: rate(http_server_requests_seconds_count{status="500"}[5m]) > 0.05
for: 5m
labels:
severity: page
告警触发后,Alertmanager 负责通知:邮件、钉钉、企业微信都行。
落地建议:先盯三个基础指标——错误率、P95 耗时、线程与连接池使用率。指标多了看不过来,告警疲劳比没告警更可怕。告警规则先设宽松再收紧:刚开始太频繁,大家会习惯性忽略,真出事反而没人响应。
初学者常栽的坑
show-details配了always,监控系统能看,黑客也能看- 健康检查里查数据库,数据库抖动导致整个应用被判 DOWN
- 指标名随手写,没有前缀规范,后期排查靠猜
- 埋了 Counter 但从不看,指标成了摆设
- 忘了暴露 prometheus 端点,抓取 404 还以为是 Prometheus 的问题
- 健康组
include写错名字:Spring Boot 默认校验组成员存在性,启动直接失败,可用management.endpoint.health.validate-group-membership=false关掉校验
本节小结
- health 汇总各健康指示器,
show-details控制细节可见性 - 自定义健康检查实现
HealthIndicator(4.x 新包名) - K8s 探针用 liveness/readiness 健康组,
add-additional-paths暴露/livez、/readyz - Micrometer 统一指标,Counter/Timer/Gauge 三种基本计量
- Prometheus 对接 = 依赖 + 暴露端点 + scrape 配置