阶段二 · Metrics 指标监控

监控指标设计

一句话总结

指标是排障的起点--它最先发出"系统出现异常"的信号.但指标设计的难点不在于"能采集什么",而在于"该采集什么":借助四个黄金信号,RED 与 USE 方法选取少数关键指标,再通过 SLI/SLO/错误预算将"系统状态是否良好"转化为可量化,可指导决策的工程问题.

前置回顾

第 01 篇确立了排障主线:指标负责发现"出事了",并指出指标的特点--低成本,全局视角,但缺乏细节.本篇将"指标"这一支柱深入讲解:先厘清指标的数据类型,再回答核心问题"到底该监控什么",最后建立 SLO 度量框架.第 03 篇将介绍如何用 Prometheus 将这些落地.

常见误区:监控所有可监控的指标

初学者搭建监控时,最常见的失败模式不是"漏了指标",而是"什么都监控,结果什么都看不出来":

一个仪表盘上挂了 80 个图表:CPU,内存,磁盘,网络,GC 次数,线程数,句柄数,各种内部计数器...凌晨告警触发,面对这 80 张图:哪个才是根因?哪些只是"跟随波动"的伴随现象?信息过载等同于没有信息,关键信号淹没在噪声中.

指标设计的核心不是"采集得多",而是"采集得准"--用尽量少的指标覆盖用户真正关心的系统健康度.要达成这一目标,需要先掌握方法论.而在方法论之前,应先认识指标的"基本构件".

四种指标类型:基本构件

几乎所有监控系统(尤其是第 03 篇将要介绍的 Prometheus)都围绕四种基本指标类型构建.混淆这些类型是初学者最常见的错误,下面逐一说明.

类型 特点 典型示例 关键注意事项
Counter 计数器 只增不减(重启归零) 请求总数,错误总数 关注其增长速率,而非绝对值
Gauge 仪表盘 可增可减,瞬时值 当前内存使用量,在线连接数,温度 直接读取当前值
Histogram 直方图 将观测值分桶统计 请求延迟分布 能够计算百分位(P99 等)
Summary 摘要 客户端预先计算分位数 请求延迟分位数 与 Histogram 类似,但分位在客户端计算

Counter 的绝对值无意义,速率才有意义

一个 Counter 显示"请求总数 = 1,203,847",这个数字本身没有实际价值--它从进程启动后持续累加.有意义的是它的变化率:"过去 1 分钟增加了 6000 → 即 100 QPS".

因此对 Counter 几乎总是使用 rate() 求速率(PromQL 详见第 03 篇),而非直接读取其值.这是新手最容易混淆的概念.

为什么延迟必须用 Histogram,而非平均值

这一点单独展开讨论,因为它至关重要,且在实践中经常被做错.假设要监控"接口延迟",直觉反应是计算平均延迟.但平均值会掩盖真实情况:

1000 个请求:
990 个耗时 10ms,10 个耗时 5000ms(这 1% 的用户等待了 5 秒)

平均延迟 = (990×10 + 10×5000) / 1000 ≈ 60ms ← 看起来正常!
但那 1% 的用户体验极差,平均值将他们"抹平"了

用户的真实体验隐藏于尾部.因此业界使用**百分位(Percentile)**来衡量:

  • P50(中位数):50% 的请求比它快--代表"典型"体验
  • P99:99% 的请求比它快,仅最慢的 1% 超过该值--代表"最差体验"的那一批用户

上述例子中,最慢的 1%(那 10 个请求)恰为 5000ms,因此 P99 ≈ 5000ms,立刻暴露了问题.Histogram 的价值正在于能够计算这些百分位--它将每个请求的耗时放入预设的桶(如 <10ms,<100ms,<1s),从分布反推百分位.监控延迟应始终关注 P99/P95,而非平均值.

只看平均延迟,如同用"全班平均分"评价教学质量:平均 85 分看似不错,却掩盖了角落里几位只得 30 分的学生.
P99 就是专门考察"最差的那几位"--因为线上最先提出投诉的,永远是这些用户.

该监控什么(一):四个黄金信号

了解了基本构件之后,回到核心问题:到底该监控哪些指标? Google SRE 给出的最经典答案是"四个黄金信号(Four Golden Signals)"--如果只能监控四类指标,就监控这四个:

信号 含义 回答的问题
延迟 Latency 处理请求所花费的时间 用户等待时间是否过久?(需将成功与失败请求的延迟分开统计)
流量 Traffic 系统承受的负载大小 当前请求量是多少?(QPS/并发数)
错误 Errors 失败请求的比率 有多少请求失败了?
饱和度 Saturation 资源的使用程度 距离"资源耗尽"还有多远?(CPU/内存/队列深度)

一个常见错误:计算延迟时将失败请求混入统计,会导致严重失真.一次快速失败(如 50ms 即返回 500 状态码)会使延迟指标"看起来变快了"--但实际是错误率在上升.

务必分别统计成功请求和失败请求的延迟,否则两个问题会相互掩盖.

该监控什么(二):RED 与 USE,两个互补视角

黄金信号偏理念层面,落地时有两个更具操作性的方法,分别从"服务"和"资源"两个角度切入--二者恰好互补.

RED:以"服务"为中心

RED 专门面向请求驱动的服务(API,微服务),仅关注三个指标:

  • Rate -- 每秒请求数(流量)
  • Errors -- 每秒失败请求数(错误)
  • Duration -- 请求耗时分布(延迟,关注 P99)

RED 的优势在于通用且统一:无论服务内部逻辑如何,这三个指标都适用.为每个微服务画上 RED 三条曲线,即可获得全局健康视图.回顾第 01 篇凌晨的告警--"下单 P99 超过 2 秒"正对应 RED 中的 D.

USE:以"资源"为中心

USE 面向资源(CPU,内存,磁盘,网络,连接池),关注三个维度:

  • Utilization -- 利用率(资源有多忙,如 CPU 80%)
  • Saturation -- 饱和度(排队等待程度,如 CPU 运行队列长度)
  • Errors -- 错误数(如磁盘 I/O 错误)

RED 发现现象,USE 定位根因--配合使用

这两个方法互为补充:RED 从用户视角发现"服务变慢了"(现象),USE 从资源视角解释"因为连接池达到饱和"(根因).

排障时的典型路径是 RED 先触发告警,再用 USE 向下深挖.RED 监控服务,USE 监控服务所依赖的资源.

将"系统状态"量化为数字:SLI/SLO/SLA

有了指标,还缺少一个关键的判断标准:多好才算"好"? P99 为 200ms 是否达标?错误率 0.5% 是否可接受?没有标准,告警阈值就只能凭感觉设置.SRE 用三个层层递进的概念来定义"好"的标准:

概念 全称 定义 示例
SLI Service Level Indicator(服务等级指标) 一个具体的测量值 过去 5 分钟内成功请求的占比
SLO Service Level Objective(服务等级目标) 为 SLI 设定的目标阈值 成功率 ≥ 99.9%
SLA Service Level Agreement(服务等级协议) 对外承诺 + 违约后果 低于 99.5% 则触发赔偿条款

三者的关系:SLI 是实测数据,SLO 是内部设定的及格线,SLA 是写入合同对客户的承诺(通常比 SLO 更宽松,留出缓冲空间). 日常工程实践中最常使用的是 SLI 和 SLO.

SLI 是本次考试的实际分数(测量值).
SLO 是自己设定的目标"本学期保持 90 分以上"(内部目标).
SLA 是与家长约定的"低于 80 分则限制娱乐时间"的协议(对外承诺 + 后果).

错误预算:SLO 最重要的衍生产物

SLO 真正改变工程决策方式的,是由其推导出的错误预算(Error Budget).逻辑简洁但影响深远:

若 SLO = 99.9% 成功率
则允许的失败比例 = 100% - 99.9% = 0.1%
→ 这 0.1% 即"错误预算"

一个月约 43200 分钟,0.1% ≈ 43 分钟
→ 本月"可承受 43 分钟服务异常"而不违反 SLO

错误预算将"稳定性"从模糊的口号转化为可支配的额度,直接指导工程决策:

  • 预算充裕 → 可以发布新版本,进行实验,上线有风险的新功能(还有试错空间)
  • 预算即将耗尽 → 冻结发布,全力保障稳定,暂缓变更

错误预算化解了开发与运维之间的经典矛盾

开发团队希望"尽快上线新功能",运维团队希望"保持稳定,减少变更"--这是 DevOps 实践中的长期拉锯.错误预算为双方提供了一个共同的,客观的决策依据:预算充足则允许发布,预算不足则冻结变更.它将"是否应该上线"从立场之争转化为数字判断.

这也呼应了 CI/CD 系列第 01 篇的 DORA 指标--稳定性并非越高越好,而是恰好满足 SLO 即可,将多余的预算用于换取迭代速度.追求 100% 可用性既不可能,也是一种资源浪费.

承上启下

本篇解决了"监控什么,好坏的标准是什么"--这属于设计层面的问题,与具体工具无关.但纸面上的指标设计要转化为实际运行的监控系统,还需要一套机制去采集,存储,查询和告警.下一篇介绍的 Prometheus 正是这一领域的事实标准:Counter/Histogram 如何被采集,P99/错误率如何用 PromQL 计算,SLO 如何转化为一条实际生效的告警规则.

快速回顾

  • 指标设计的核心是"采得准"而非"采得多":80 个图表 = 信息过载 = 有效信息为零
  • 四种类型:Counter(只增,关注 rate 速率),Gauge(瞬时值),Histogram(分桶统计,可计算百分位),Summary
  • 延迟必须使用百分位(P99/P95)而非平均值:平均值会将尾部的糟糕体验抹平
  • 该监控什么:四个黄金信号(延迟/流量/错误/饱和度);RED 关注服务(Rate/Errors/Duration),USE 关注资源(Utilization/Saturation/Errors),二者互补--RED 发现现象,USE 定位根因
  • SLI/SLO/SLA:测量值/内部目标/对外承诺;将"系统好坏"转化为可量化,可指导决策的数字
  • 错误预算 = 100% − SLO:将稳定性转化为可支配的额度,为"该发布还是该冻结"提供客观裁决依据

Histogram 和 Summary 应如何选择?

大多数场景选择 Histogram.关键差异在于"百分位在哪里计算":Summary 在客户端(被监控的服务进程内)预先计算分位数,优点为精确,查询开销低,缺点是无法跨实例聚合(三个实例各自的 P99 无法合并为全局 P99).Histogram 将原始分桶数据交由服务端(Prometheus)计算,支持跨实例聚合得出全局百分位--这在多副本的微服务场景几乎是刚需.代价是桶需要预先设计,且结果为估算值.生态也更偏向 Histogram.

SLO 应设定为多少?直接定 99.999%(五个九)不是更安全?

恰恰相反,盲目追求高可用是常见误区.每增加一个"9",成本与复杂度均呈指数级增长(99.9% 允许月停机 43 分钟,99.99% 仅剩 4 分钟,99.999% 仅剩 26 秒--这意味着几乎没有发布和试错空间).正确做法是从用户实际需求反推:当用户根本感知不到 99.9% 与 99.99% 之间的差异时,设定 99.9% 即已足够,将节余的错误预算用于提升迭代速度.SLO 是业务决策,而非技术竞赛.

动手练习

  1. 套用 RED 和 USE:为负责的一个服务套用 RED 方法,写出其三个核心指标;再套用 USE 方法,列出其依赖的关键资源(连接池?线程池?)及对应的利用率/饱和度指标.
  2. 审视平均值延迟图表:在现有监控中找出一张使用平均值衡量延迟的图表,分析改用 P99 的理由--并估算若存在少量极慢请求,平均值会造成多大程度的误导.
  3. 计算错误预算:为该服务设定一个 SLO(如成功率 99.9%),手动计算其月度错误预算(以分钟计).
  4. 对比预算与实际:回顾该服务上月的故障时长,与错误预算对比:本月预算是超支还是有结余?若已超支,按错误预算的逻辑,当前应采取的行动是"继续发布"还是"冻结变更以恢复稳定"?