3. 数据采集与监控:关键指标与 Prometheus + Grafana 体系搭建

体量异常分析,说白了就是一场「数据侦探」的游戏。你连现场证据都采集不全,怎么破案?

我个人习惯,在搭建监控体系前,先想清楚一个问题:到底要看哪些指标? 不是所有数据都有用,抓错了反而淹没了真正的信号。

3.1 五大核心指标:你必须盯紧的「生命体征」

我把它们称为系统的「五根手指」。缺了哪根,你都抓不住问题的本质。

指标 全称 一句话解释 我踩过的坑
QPS Queries Per Second 每秒查询数,衡量系统吞吐 曾经把静态资源的请求也算进去,导致 QPS 虚高,掩盖了真正的业务接口瓶颈
TPS Transactions Per Second 每秒事务数,侧重完整业务 支付场景下,TPS 掉 10%,老板的电话就来了
RT Response Time 响应时间,用户体验的命根 只看平均值是骗人的,P99 才是真相
错误率 Error Rate 失败请求占比 5xx 和 4xx 必须分开看,混在一起等于没看
资源利用率 CPU / MEM / IO / NET 基础设施的「体力」 CPU 100% 不一定是坏事,可能是你在做离线计算

我的黄金法则: 先定指标,再搭工具。别反过来。

3.2 指标采集:从「裸数据」到「可观测」

采集方式就三种,我按推荐度排个序:

  1. 埋点上报 —— 最精确,业务代码里主动打点。适合 QPS、TPS、RT、错误率。
  2. 日志解析 —— 无侵入,但延迟高。适合历史回溯。
  3. 系统指标拉取 —— 用 Node Exporter 这类工具。适合资源利用率。

嗯,这里要注意:埋点不要乱埋。我曾经见过一个团队,每个接口埋了 20 个点,最后 Prometheus 内存直接爆了。你想想看,这跟没埋有什么区别?

3.2.1 实战:用 Prometheus Client 埋点

以 Go 为例,我习惯这样写:

// 定义指标
var (
    apiRequests = prometheus.NewCounterVec(
        prometheus.CounterOpts{
            Name: "api_requests_total",
            Help: "Total number of API requests.",
        },
        []string{"method", "endpoint", "status"},
    )
    requestDuration = prometheus.NewHistogramVec(
        prometheus.HistogramOpts{
            Name:    "api_request_duration_seconds",
            Help:    "API request latency distributions.",
            Buckets: prometheus.DefBuckets, // 默认桶:0.005, 0.01, 0.025, ...
        },
        []string{"method", "endpoint"},
    )
)

// 在 HTTP 中间件中采集
func MetricsMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        // 包装 ResponseWriter 以捕获状态码
        wrapped := &responseWriter{ResponseWriter: w, statusCode: 200}
        next.ServeHTTP(wrapped, r)

        // 记录 QPS(通过 Counter 的速率)
        apiRequests.WithLabelValues(r.Method, r.URL.Path, strconv.Itoa(wrapped.statusCode)).Inc()

        // 记录 RT(通过 Histogram)
        requestDuration.WithLabelValues(r.Method, r.URL.Path).Observe(time.Since(start).Seconds())
    })
}

小技巧: Histogram 的桶(Buckets)要按你的业务 RT 分布来设。默认桶对高延迟服务不友好,我一般会加几个大桶:0.1, 0.5, 1, 2, 5。

3.3 Prometheus + Grafana:监控体系的「黄金搭档」

为什么选这对组合?说白了,Prometheus 负责「存和查」,Grafana 负责「画和看」。分工明确,各司其职。

3.3.1 架构图:数据流长什么样?

我画了一张图,帮你理清数据从产生到展示的全链路:

Prometheus + Grafana 监控数据流 业务应用 Node Exporter /metrics 拉取 Prometheus Server TSDB + AlertManager PromQL 查询 Grafana Dashboard AlertManager 钉钉 / 邮件 / PagerDuty 💡 关键说明: 1. Prometheus 主动拉取(Pull)模式,比推模式(Push)更可靠,避免目标端压力过大。 2. AlertManager 负责去重、分组、路由告警,避免「告警风暴」。

3.3.2 搭建步骤:别怕,就三步

我每次搭建新环境,都按这个流程走,基本不会出岔子:

  1. 部署 Prometheus —— 用 Docker 最省事,配置文件写好 target 就行。
  2. 配置数据源 —— 在 Grafana 里添加 Prometheus 数据源,URL 填 http://prometheus:9090。
  3. 导入 Dashboard —— 别自己画,去 Grafana 官方市场找现成的,比如 Node Exporter Full 和 Spring Boot Statistics。

⚠️ 避坑指南: 我曾经因为 Prometheus 的 scrape_interval 设成 5s,导致目标服务器负载飙升。对于大多数场景,15s 足够了。别贪心。

3.3.3 关键 PromQL 查询:你得会写这几句

PromQL 是 Prometheus 的查询语言。我挑几个最常用的,你直接拿去用:

查询目标 PromQL 语句
QPS(每秒请求数) rate(api_requests_total[1m])
P99 响应时间 histogram_quantile(0.99, rate(api_request_duration_seconds_bucket[5m]))
错误率 sum(rate(api_requests_total{status=~"5.."}[5m])) / sum(rate(api_requests_total[5m]))
CPU 使用率 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[1m])) * 100)

我的习惯: 把常用的 PromQL 存成 Grafana 的「变量」,这样切换环境时不用改查询语句,只改变量值就行。

3.4 告警配置:别等用户骂你才醒

监控不配告警,等于白干。我见过太多团队,Dashboard 画得花里胡哨,结果半夜出事了没人知道。

告警规则我一般这样写:

# prometheus-rules.yml
groups:
  - name: api_alerts
    rules:
      - alert: HighErrorRate
        expr: |
          sum(rate(api_requests_total{status=~"5.."}[5m]))
          /
          sum(rate(api_requests_total[5m])) > 0.05
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "API 错误率超过 5%"
          description: "当前错误率 {{ $value | humanizePercentage }},已持续 2 分钟"

      - alert: HighP99Latency
        expr: |
          histogram_quantile(0.99, rate(api_request_duration_seconds_bucket[5m])) > 2
        for: 1m
        labels:
          severity: warning
        annotations:
          summary: "P99 响应时间超过 2 秒"

核心原则: 告警要「少而准」。一天响 100 次,没人会当回事。我一般把告警分为三级:Critical(立即处理)、Warning(上班看)、Info(周报里提一嘴)。

3.5 本章小结:你的「监控三件套」

搭建完这套体系,你至少应该能回答这三个问题:

  • 现在系统健康吗? —— 看 Grafana Dashboard 的全局视图。
  • 哪里出了问题? —— 看 PromQL 下钻到具体接口或实例。
  • 什么时候出的问题? —— 看告警记录和事件时间线。