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 指标采集:从「裸数据」到「可观测」
采集方式就三种,我按推荐度排个序:
- 埋点上报 —— 最精确,业务代码里主动打点。适合 QPS、TPS、RT、错误率。
- 日志解析 —— 无侵入,但延迟高。适合历史回溯。
- 系统指标拉取 —— 用 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 架构图:数据流长什么样?
我画了一张图,帮你理清数据从产生到展示的全链路:
3.3.2 搭建步骤:别怕,就三步
我每次搭建新环境,都按这个流程走,基本不会出岔子:
- 部署 Prometheus —— 用 Docker 最省事,配置文件写好 target 就行。
- 配置数据源 —— 在 Grafana 里添加 Prometheus 数据源,URL 填
http://prometheus:9090。 - 导入 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 下钻到具体接口或实例。
- 什么时候出的问题? —— 看告警记录和事件时间线。