3. 运行时性能监控体系搭建

当 Spring Boot 应用进入生产环境后,日志只能回答“发生了什么”,却很难回答“现在有多慢、慢在哪里、是否正在恶化”。运行时性能监控体系要解决的是后一类问题:把 JVM、HTTP 请求、数据库连接池、线程池等运行时状态,以可采集、可存储、可查询、可告警的形式持续暴露出来。本节围绕 Spring Boot Actuator、Micrometer、Prometheus 与 Grafana 四层结构,讲清它们各自的职责边界,并给出一套可落地的集成与关键指标采集方案。

四层职责:从埋点到看板

这套体系是一条清晰的数据链路,而不是四个孤立工具。Actuator 负责在应用内暴露端点,Micrometer 负责以统一门面采集和转换指标,Prometheus 负责按固定周期拉取并存储时序数据,Grafana 负责查询与可视化。理解这条链路,才能判断“指标没出来”到底断在哪一层。

Spring Boot 运行时监控数据链路 Spring Boot 应用 Actuator 端点 /actuator/prometheus Micrometer 门面 MeterRegistry 采集来源 JVM / HTTP / 连接池 线程池 / 缓存 / 自定义 @Timed / Counter / Gauge HTTP 拉取 15s 间隔 Prometheus scrape 抓取 TSDB 时序存储 PromQL 查询 数据源 HTTP API Grafana Dashboard 面板 告警规则 Alerting 趋势与容量分析 断点定位:端点无输出 → 查 Actuator/Micrometer;Prometheus 无 target → 查抓取配置;Grafana 无数据 → 查 PromQL 与数据源

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_secondsHistogramHTTP 请求耗时分布,按 uri、method、status 维度拆分,用于算 P95/P99 与错误率
jvm_memory_used_bytesGauge各内存区已用字节,配合 max 观察堆压力与 GC 触发频率
jvm_gc_pause_secondsSummary/HistogramGC 停顿时间,关注 P99 与单位时间累计停顿
hikaricp_connections_activeGauge连接池活跃连接数,持续接近 maximumPoolSize 说明存在连接争用
hikaricp_connections_pendingGauge等待获取连接的线程数,大于 0 即出现排队
executor_pool_size / executor_queuedGauge线程池大小与排队任务数,用于判断异步任务是否积压
system_cpu_usageGauge进程 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 触发告警。

指标标签基数要控制。把用户 ID、订单号这类高基数字段作为标签,会导致时序数量爆炸,拖垮 Prometheus。高基数信息应放在日志或链路追踪中,而非指标标签。
Actuator 端点默认只暴露 health 和 info,且生产环境必须限制访问。建议将 /actuator 绑定到内网管理端口,或通过 Spring Security 做鉴权,避免敏感指标与堆转储端点对外暴露。

至此,一条从应用内埋点到可视化告警的完整链路已经打通。判断体系是否真正可用,不看面板是否好看,而看三个问题能否快速回答:当前请求慢不慢、慢在哪个环节、是否正在恶化。当这三个问题都能在 Grafana 上通过下钻得到答案时,运行时监控体系才算真正落地。