3. 运行时性能监控体系搭建
当 Spring Boot 应用进入生产环境后,日志只能回答“发生了什么”,却很难回答“现在有多慢、慢在哪里、是否正在恶化”。运行时性能监控体系要解决的是后一类问题:把 JVM、HTTP 请求、数据库连接池、线程池等运行时状态,以可采集、可存储、可查询、可告警的形式持续暴露出来。本节围绕 Spring Boot Actuator、Micrometer、Prometheus 与 Grafana 四层结构,讲清它们各自的职责边界,并给出一套可落地的集成与关键指标采集方案。
四层职责:从埋点到看板
这套体系是一条清晰的数据链路,而不是四个孤立工具。Actuator 负责在应用内暴露端点,Micrometer 负责以统一门面采集和转换指标,Prometheus 负责按固定周期拉取并存储时序数据,Grafana 负责查询与可视化。理解这条链路,才能判断“指标没出来”到底断在哪一层。
Actuator 与 Micrometer 的集成
Actuator 提供端点,Micrometer 提供指标。Spring Boot 2.x 之后,只要引入 spring-boot-starter-actuator 和 micrometer-registry-prometheus,Micrometer 就会自动装配一个 PrometheusMeterRegistry,并把 JVM、系统、HTTP 等基础指标注册进去。关键配置如下:
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
endpoint:
health:
show-details: when_authorized
metrics:
tags:
application: order-service
env: prod
distribution:
percentiles-histogram:
http.server.requests: true
slo:
http.server.requests: 50ms,100ms,200ms,500ms,1s
其中 management.metrics.tags 会作为公共标签附加到所有指标上,便于在多实例、多环境下按应用名和环境过滤。percentiles-histogram 开启后,Micrometer 会为 HTTP 请求生成直方图桶,Prometheus 端即可用 histogram_quantile 计算 P95、P99 分位延迟,这是排查“平均延迟正常但长尾严重”问题的关键。
关键指标采集与含义
指标不是越多越好,先抓住能反映系统健康度的核心集合。下表列出生产环境最值得优先接入的指标及其判读方式。
| 指标名 | 类型 | 含义与判读 |
|---|---|---|
| http_server_requests_seconds | Histogram | HTTP 请求耗时分布,按 uri、method、status 维度拆分,用于算 P95/P99 与错误率 |
| jvm_memory_used_bytes | Gauge | 各内存区已用字节,配合 max 观察堆压力与 GC 触发频率 |
| jvm_gc_pause_seconds | Summary/Histogram | GC 停顿时间,关注 P99 与单位时间累计停顿 |
| hikaricp_connections_active | Gauge | 连接池活跃连接数,持续接近 maximumPoolSize 说明存在连接争用 |
| hikaricp_connections_pending | Gauge | 等待获取连接的线程数,大于 0 即出现排队 |
| executor_pool_size / executor_queued | Gauge | 线程池大小与排队任务数,用于判断异步任务是否积压 |
| system_cpu_usage | Gauge | 进程 CPU 使用率,结合负载判断是否算力瓶颈 |
自定义业务指标同样重要。例如统计下单成功率,可用 Counter 记录成功与失败次数:
@RestController
public class OrderController {
private final Counter orderSuccess;
private final Counter orderFail;
public OrderController(MeterRegistry registry) {
this.orderSuccess = Counter.builder("order.create")
.tag("result", "success").register(registry);
this.orderFail = Counter.builder("order.create")
.tag("result", "fail").register(registry);
}
@PostMapping("/orders")
public Order create(@RequestBody OrderReq req) {
try {
Order o = service.create(req);
orderSuccess.increment();
return o;
} catch (Exception e) {
orderFail.increment();
throw e;
}
}
}
方法级耗时可用 @Timed 注解,Micrometer 会自动生成带 method 标签的计时器,无需手写计时逻辑。
Prometheus 抓取配置
Prometheus 采用拉模型,需要在 prometheus.yml 中声明抓取目标。生产环境通常配合服务发现,静态配置适合验证阶段:
scrape_configs:
- job_name: 'spring-boot-app'
metrics_path: '/actuator/prometheus'
scrape_interval: 15s
static_configs:
- targets: ['10.0.1.21:8080', '10.0.1.22:8080']
labels:
env: prod
抓取间隔 15s 是常见折中:过密会增加应用与存储压力,过疏会丢失短时尖峰。配置完成后,在 Prometheus 的 /targets 页面确认目标状态为 UP,若为 DOWN,优先检查网络连通性、端点路径与鉴权配置。
Grafana 看板与告警
Grafana 添加 Prometheus 为数据源后,即可用 PromQL 构建面板。几个高频查询示例:
# 请求 P95 延迟
histogram_quantile(0.95,
sum(rate(http_server_requests_seconds_bucket[5m])) by (le, uri))
# 5xx 错误率
sum(rate(http_server_requests_seconds_count{status=~"5.."}[5m]))
/ sum(rate(http_server_requests_seconds_count[5m]))
# 连接池等待线程
hikaricp_connections_pending{application="order-service"}
看板建议按“总览—JVM—HTTP—数据库—线程池”分层组织,总览页放错误率、P95 延迟、CPU、GC 停顿四个核心信号,异常时再下钻到具体面板。告警规则可基于 PromQL 设置阈值,例如 5xx 错误率持续 5 分钟超过 1% 触发告警,GC P99 停顿超过 500ms 触发告警。
/actuator 绑定到内网管理端口,或通过 Spring Security 做鉴权,避免敏感指标与堆转储端点对外暴露。至此,一条从应用内埋点到可视化告警的完整链路已经打通。判断体系是否真正可用,不看面板是否好看,而看三个问题能否快速回答:当前请求慢不慢、慢在哪个环节、是否正在恶化。当这三个问题都能在 Grafana 上通过下钻得到答案时,运行时监控体系才算真正落地。