跳转至

监控、仪表盘与可观测性 — 让系统自己开口说话

这一章讲什么: 系统出问题的时候,你怎么知道、怎么知道为什么、怎么知道坏在哪一环。 答案是一套互相印证的三层信号(指标、日志、追踪)加一组工具 (Prometheus、Grafana、OpenSearch、Jaeger)和一套度量框架(RED、黄金信号、SLO)。 第 03 章讲了「信号怎么从代码里发出来」,本章讲「信号发出来之后怎么变成答案」。

1. 主线例子:一次支付延迟的六步诊断

本章的主线例子,是原书金融案例的完整推演:支付网关出现延迟。

  第 1 步 检测:Prometheus 告警——Payment API 延迟 > 300ms 持续 5 分钟
  第 2 步 指标定位:Grafana 上看 RED——请求率正常,错误率和 P95 延迟上升
      → 不是流量激增,是性能退化
  第 3 步 日志给上下文:OpenSearch 里按 trace_id 过滤,
      看到「Payment gateway timeout」、响应 4500ms
  第 4 步 追踪定位置:Jaeger 里这笔请求的 trace——
      API 网关→Auth(50ms)→用户库(120ms)→会话缓存(10ms)……
      热点在某个 span,瓶颈锁定在具体服务
  第 5 步 修复:查该服务最近的部署/配置变更/依赖
  第 6 步 验证:指标和 trace 确认延迟回到基线

  图说:六步 = 检测→指标→日志→追踪→修复→验证。
  每一步用一类工具答一个问题;时间和数值沿原书示例量级。

旧式监控在第 1 步就断了——它告诉你 CPU 高,但不告诉你为什么。可观测性的全部加成, 在第 3、4 步。本章结构:§2 三支柱,§3 度量框架,§4 工具栈,§5 仪表盘设计, §6 六步调试法展开,§7 把检测时间(MTTD)压下去。

2. 三支柱:各有分工,合力才有答案

支柱 回答 形态
指标(metrics) 发生了什么——错误率飙升、延迟变长 带时间戳的数值(Prometheus 存的时间序列);四种类型 Gauge/Counter/Histogram/Summary(第 03 章详讲过)
日志(logs) 为什么——那个时刻具体出了什么事 事件记录,结构化 JSON 优先;要集中收集、带关联 ID
追踪(traces) 在哪里——请求卡在哪一跳 span 的层级:一笔 trace 拆成多个 span,各带耗时1

原书的追踪例子(照抄结构):登录请求穿过 网关→认证(50ms)→用户库(120ms)→会话缓存(10ms), 如果慢主要在第二个 span,瓶颈在数据库层而不是应用代码2。

三支柱不是三个工具,是同一系统的三个视角;指标触发告警,日志解释来源, 追踪 pinpoint 位置——三环相扣才叫可观测3。

3. 三套度量框架:量什么、怎么量、量到多少算够

3.1 RED:面向服务的三指标

RED:Rate(每秒请求数)、Errors(失败请求比例)、Duration(处理时长,看 P95/P99)。 服务仪表盘的标配;速率稳定但 Duration 和 Errors 齐升 = 性能退化而非流量问题4。

3.2 四个黄金信号:面向系统的四指标

谷歌 SRE 提出:延迟(含失败请求的延迟)、流量(需求体量)、错误率、 饱和度(离资源上限还有多近)——比 RED 多一个饱和度, 能在故障发生前看到容量预警5。

3.3 SLI/SLO/SLA:从工程到合同的阶梯

  • SLI(服务等级指标):量化测量,如可用率;
  • SLO(服务等级目标):SLI 的目标值,工程内部用;
  • SLA(服务等级协议):对客户的合同承诺,违约有罚则6。

支付 API 的完整算例(照原书,数字给了量感):SLI = 成功支付请求的百分比; SLO = 月可用性 99.95%;错误预算 = 0.05%——月处理 1000 万笔请求, 预算就是 5000 笔失败;预算烧完,暂停发版先补稳定7。这个例子把第 01 章 「错误预算」的抽象定义变成了能算的数。

4. 工具栈:Prometheus + Grafana + OpenSearch + Jaeger + OTel

4.1 Prometheus:指标采集与告警

开源监控(出身 SoundCloud,CNCF 项目),拉取模型:定时去各目标抓取 /metrics。 四大特性:多维数据模型(指标名 + 标签)、PromQL 查询语言、Alertmanager 告警联动、 服务发现(在 K8s 里自动找目标)8。

三个生产限制(原书罕见地讲了工具的天花板):

  1. 没有内建长期存储——默认保留以天/周计;
  2. 单节点架构,量大了查询变慢;
  3. 高基数标签:user_id/request_id 这类无界值会让时间序列爆炸,内存磁盘撑爆9。

对应解法:Thanos(加对象存储长存 + 跨实例全局查询)、Cortex / Grafana Mimir (水平扩展、多租户)——指标采集端代码一行不改10。基数纪律四条: 无界值不做标签、只用有界标签(服务/端点/方法/状态码)、指标用于聚合而非排错 (细节去日志和 trace)、定期审查11。

4.2 Grafana:可视化层

接多种数据源(Prometheus/OpenSearch/CloudWatch),图形、仪表盘变量、 告警通知、模板共享。例子的 PromQL:avg(rate(container_cpu_usage_seconds_total[5m])) by (pod)12。

4.3 OpenSearch:日志分析

出身 Elasticsearch 的开源搜索套件:日志索引(给每行日志建目录便于秒查) + 近实时查询 + 仪表盘; 用 Fluentd/Filebeat 收集;例子查询:按 level: ERROR 过滤再按服务聚合, 哪一组件在报错一目了然13。

4.4 Jaeger:分布式追踪

Uber 开源、CNCF 项目。span 记服务名/操作/时长,UI 画出完整请求流和依赖图; OpenTelemetry SDK 插桩后直接导出14。

4.5 OpenTelemetry:统一管道,反锁定

OTel 不是监控工具,是采集与导出的开放标准:代码插桩一次, 数据可以分发给任意后端。Collector 三段式架构—— Receivers(收:OTLP/Prometheus/Jaeger)→ Processors(处理:批处理、 采样、过滤、改属性)→ Exporters(发:Prometheus/Jaeger/OpenSearch)。 采样策略、脱敏、删高基数属性在中央做,应用代码不动15。

四工具集成后的工作流(原书例子):API 延迟上升(Prometheus 指标)→ Grafana 看图 → OpenSearch 日志交叉验证 → Jaeger 定位到具体服务16。

5. 服务专属仪表盘

通用仪表盘对具体服务没有意义:计算密集服务和数据库服务该看的完全不同17。 仪表盘分三类用途:运维(实时健康)、分析(长期趋势)、业务(转化/收入)。 设计六原则:顶部只放关键指标、图形类型匹配数据、颜色阈值一致(绿黄红)、 时间范围可切换、面板带下钻链接、性能优化(缓存/轻查询)18。

指标四类(支付 API 例子照原书表 10.1):性能(平均响应时间)、可靠(错误率%)、 资源(CPU)、业务(每分钟成功交易数)。基建层再加 USE 方法 (Utilization/Saturation/Errors)19。

Grafana 建盘五步:接数据源 → 建面板选图形 → 写查询(PromQL/Lucene)→ 加变量($service_name 一套模板跨环境)→ 设告警阈值和通知渠道20。 维护五条:定期清理指标、用 Terraform/JSON 把仪表盘当代码管、给每面板写文档、 盯查询性能、跨盘统一命名配色21。

案例(初创公司,数字无出处):各团队仪表盘碎片化、无标准,排障耗时; 统一策略——三支柱合一、每服务固定五面板(请求率/延迟/错误率/CPU/trace 时长)、 Terraform 自动建盘——MTTD 降 40%,分钟级定位22。

6. 分布式系统的调试工作流

分布式排障的四大挑战:故障点多(任一服务都可能坏)、行为不确定(网络延迟/ 重试/负载均衡引入变数)、日志分散、瞬态错误(特定负载下出现,查时已消失)23。

六步工作流(§1 主线例子的展开,照原书)24:

步 动作 工具
1 检测 告警/仪表盘发现异常 Prometheus + Grafana
2 指标分析 局部还是全局? 相关指标(RED/黄金信号)
3 日志关联 按 correlation/trace ID 过滤 OpenSearch
4 追踪定位 可视化请求流找瓶颈 Jaeger
5 定点修复 查部署/配置/依赖 变更记录
6 验证 确认恢复 指标 + trace

收益表(原书表 10.2):更快解决、更高可靠、协作统一、主动发现、开发者 ownership25。

7. 压缩检测时间:MTTD 的完整策略

MTTD(平均检测时间)是可观测性成熟度的定义性指标:故障发生到被发现的时间。 每分钟的检测延迟都在放大损失——大促中 20 分钟才发现支付失败, 就是几千笔交易没了;检测不可靠,团队就不敢快发,发布速度连坐受损26。

六个加速策略27:

  1. 可行动的告警:「Payment API 延迟 > 300ms 持续 5 分钟」远好过「CPU spike」—— 阈值、服务、时长、严重度四要素齐全;
  2. AI 异常检测:学基线、抓偏离,静态阈值管不住的低流量时段异常也能浮出;
  3. 三支柱联动:一个仪表盘看全,检测从分钟级到秒级;
  4. 可观测性进 CI/CD:金丝雀、性能基线、告警演练——故障在用户看到前被拦;
  5. 合成监控:模拟关键用户旅程(登录/搜索/结账)每分钟从多区域打探测交易, 真实流量低时依然有人站岗;
  6. 实时仪表盘:只放最敏感指标(延迟/错误率/吞吐/饱和度),阈值配色,自动刷新。

度量体系(原书表 10.3,带目标值)28:

指标 定义 目标
MTTD 故障发生到检测 < 5 分钟
MTTR 检测到修复 靠自动化与自愈持续降
告警精确率 真警报占比 > 80%
事故频率 每月重复问题数 逐月降
误报率 无实际影响的告警 < 10%

案例(全球金融服务商,原书数字):原来静态阈值告警,误报不断、漏报也有—— 支付网关延迟 30 分钟没被发现;上了 Prometheus+OpenSearch+Jaeger+Grafana + ML 异常检测 + 每分钟合成交易后,同类异常 2 分钟内被检出, MTTD 从 20 分钟降到 3 分钟以下,MTTR 降近 50%29。

判断(我们的,不是书里的): 本章工具栈章节里最有分量的是 Prometheus 「三个生产限制」那半节——多数教材只讲工具能做什么,这章讲了工具做不到什么 (长存、水平扩展、高基数),并且每个限制都给了对应的架构解法。 读任何工具文档时带着这三个问题问:数据能存多久?规模天花板在哪? 什么输入会把它打爆? 这比背特性列表值钱。 如果错,会错在: 云厂商托管的指标服务(以及 Mimir 这类新后端)正在 逐项抹平这些限制,「Prometheus 单机不够用」的紧迫性在下降; 但「高基数打爆存储」这条是数据结构的代价,换后端也只会缓解不会消失。

8. 边界与局限

  1. 三支柱的「关联」只给了理念:trace_id 怎么在四个工具间贯通, 落地配置比书里写的繁琐一个数量级。
  2. 异常检测/AI 部分是两段愿景,没有任何机制细节——怎么定基线、 误报怎么处理,全留给读者。
  3. 告警疲劳(alert fatigue)只在精确率指标里间接出现,没有给「告警瘦身」 的具体操作(聚合、抑制、路由)。
  4. 成本面缺失:日志量级、采样率、保留期对账单的联动没有讲(第 03 章有一小节, 本章没接)。
  5. 案例数字(-40%、20→3 分钟)无出处,作量级参考。

9. 可带走的

  1. 指标答「什么」、日志答「为什么」、追踪答「哪里」;单支柱都只是碎片;
  2. RED 管服务(速率/错误/时长),黄金信号管系统(+饱和度),SLI/SLO/SLA 管承诺;
  3. 错误预算能算:99.95% × 月 1000 万笔 = 5000 笔的额度,烧完停发版;
  4. Prometheus 三限制:没长存、单机瓶颈、高基数;解法是 Thanos/Mimir + 基数纪律;
  5. 标签只用有界值;指标做聚合,排错靠日志和 trace;
  6. OTel 一次插桩处处可发;采样与脱敏在中央 Collector 做;
  7. 仪表盘按服务定制,五面板起步,顶部放 SLO,当代码管;
  8. 调试六步:检测→指标→日志→追踪→修复→验证;
  9. MTTD < 5 分钟、告警精确率 > 80%、误报 < 10%——可观测性自身的 KPI。

10. 原文地图

主题 原书章 原文位置
三支柱分工与追踪例子 Introduction(第 10 章) text/28-fm-introduction.txt:64(搜「what happened」) · text/28-fm-introduction.txt:185(搜「4b825dc642cb6eb9」)
RED 与四个黄金信号 Introduction(第 10 章) text/28-fm-introduction.txt:232(搜「Rate」) · text/28-fm-introduction.txt:248(搜「Google」)
SLI/SLO/SLA 与支付算例 Introduction(第 10 章) text/28-fm-introduction.txt:275(搜「SLI」) · text/28-fm-introduction.txt:305(搜「5,000 failed requests」)
Prometheus 特性与拉取模型 Introduction(第 10 章) text/28-fm-introduction.txt:323(搜「pull-based」) · text/28-fm-introduction.txt:333(搜「Multi-dimensional」)
三大限制与 Thanos/Cortex/Mimir Introduction(第 10 章) text/28-fm-introduction.txt:385(搜「long-term storage」) · text/28-fm-introduction.txt:391(搜「high-cardinality」) · text/28-fm-introduction.txt:400(搜「Thanos」)
Grafana/OpenSearch/Jaeger Introduction(第 10 章) text/28-fm-introduction.txt:435(搜「visualization platform」) · text/28-fm-introduction.txt:491(搜「Elasticsearch」) · text/28-fm-introduction.txt:559(搜「Uber」)
OTel Collector 三段式 Introduction(第 10 章) text/28-fm-introduction.txt:666(搜「Receivers」) · text/28-fm-introduction.txt:676(搜「sampling」)
仪表盘原则与支付 API 指标表 Introduction(第 10 章) text/28-fm-introduction.txt:777(搜「Prioritize key metrics」) · text/28-fm-introduction.txt:934(搜「Table 10.1」)
统一仪表盘案例(-40%) Introduction(第 10 章) text/28-fm-introduction.txt:1009(搜「five standard panels」) · text/28-fm-introduction.txt:1016(搜「40%」)
六步调试工作流 Introduction(第 10 章) text/28-fm-introduction.txt:1080(搜「Detect the issue」) · text/28-fm-introduction.txt:1092(搜「Pinpoint and fix」)
MTTD 六策略与 KPI 表 Introduction(第 10 章) text/28-fm-introduction.txt:1223(搜「Latency > 300 ms」) · text/28-fm-introduction.txt:1247(搜「Synthetic monitoring」) · text/28-fm-introduction.txt:1305(搜「Reduce below 5 minutes」)
金融案例(20→3 分钟) Introduction(第 10 章) text/28-fm-introduction.txt:1391(搜「30 minutes」) · text/28-fm-introduction.txt:1397(搜「under three」)

  1. 出处:「Introduction」(第 10 章)第 61–64 段(text/28-fm-introduction.txt:64,搜「what happened」)。 ↩

  2. 出处:「Introduction」(第 10 章)第 185–197 段(text/28-fm-introduction.txt:185,搜「4b825dc642cb6eb9」)。 ↩

  3. 出处:「Introduction」(第 10 章)第 206 段(text/28-fm-introduction.txt:206,搜「single pane of glass」)。 ↩

  4. 出处:「Introduction」(第 10 章)第 228–242 段(text/28-fm-introduction.txt:242,搜「performance degradation rather than a traffic surge」)。 ↩

  5. 出处:「Introduction」(第 10 章)第 245–265 段(text/28-fm-introduction.txt:248,搜「Google」;text/28-fm-introduction.txt:261,搜「Saturation」)。 ↩

  6. 出处:「Introduction」(第 10 章)第 268–285 段(text/28-fm-introduction.txt:275,搜「SLI」)。 ↩

  7. 出处:「Introduction」(第 10 章)第 288–305 段(text/28-fm-introduction.txt:298,搜「99.95%」;text/28-fm-introduction.txt:305,搜「5,000 failed requests」)。 ↩

  8. 出处:「Introduction」(第 10 章)第 317–342 段(text/28-fm-introduction.txt:323,搜「pull-based」;text/28-fm-introduction.txt:339,搜「Alertmanager」)。 ↩

  9. 出处:「Introduction」(第 10 章)第 385–391 段(text/28-fm-introduction.txt:391,搜「high-cardinality」)。 ↩

  10. 出处:「Introduction」(第 10 章)第 394–406 段(text/28-fm-introduction.txt:400,搜「Thanos」;text/28-fm-introduction.txt:403,搜「Cortex」)。 ↩

  11. 出处:「Introduction」(第 10 章)第 416–425 段(text/28-fm-introduction.txt:416,搜「unbounded」;text/28-fm-introduction.txt:422,搜「aggregation, not debugging」)。 ↩

  12. 出处:「Introduction」(第 10 章)第 435–485 段(text/28-fm-introduction.txt:476,搜「container_cpu_usage_seconds_total」)。 ↩

  13. 出处:「Introduction」(第 10 章)第 491–550 段(text/28-fm-introduction.txt:523,搜「match」;text/28-fm-introduction.txt:550,搜「Fluentd」)。 ↩

  14. 出处:「Introduction」(第 10 章)第 553–624 段(text/28-fm-introduction.txt:559,搜「Uber」;text/28-fm-introduction.txt:618,搜「process_payment」)。 ↩

  15. 出处:「Introduction」(第 10 章)第 656–696 段(text/28-fm-introduction.txt:666,搜「Receivers」;text/28-fm-introduction.txt:676,搜「without modifying application code」)。 ↩

  16. 出处:「Introduction」(第 10 章)第 708–736 段(text/28-fm-introduction.txt:728,搜「increase in API latency」)。 ↩

  17. 出处:「Introduction」(第 10 章)第 741–768 段(text/28-fm-introduction.txt:747,搜「compute-intensive」)。 ↩

  18. 出处:「Introduction」(第 10 章)第 770–792 段(text/28-fm-introduction.txt:783,搜「green for healthy」)。 ↩

  19. 出处:「Introduction」(第 10 章)第 806–934 段(text/28-fm-introduction.txt:829,搜「USE」;text/28-fm-introduction.txt:934,搜「Table 10.1」)。 ↩

  20. 出处:「Introduction」(第 10 章)第 940–959 段(text/28-fm-introduction.txt:953,搜「$namespace」)。 ↩

  21. 出处:「Introduction」(第 10 章)第 973–992 段(text/28-fm-introduction.txt:983,搜「Terraform provider」)。 ↩

  22. 出处:「Introduction」(第 10 章)第 996–1016 段(text/28-fm-introduction.txt:1009,搜「five standard panels」;text/28-fm-introduction.txt:1016,搜「40%」)。 ↩

  23. 出处:「Introduction」(第 10 章)第 1031–1051 段(text/28-fm-introduction.txt:1041,搜「Non-deterministic」;text/28-fm-introduction.txt:1047,搜「Transient errors」)。 ↩

  24. 出处:「Introduction」(第 10 章)第 1074–1098 段(text/28-fm-introduction.txt:1080,搜「Detect the issue」;text/28-fm-introduction.txt:1086,搜「correlation IDs」)。 ↩

  25. 出处:「Introduction」(第 10 章)第 1101–1193 段(text/28-fm-introduction.txt:1193,搜「Table 10.2」)。 ↩

  26. 出处:「Introduction」(第 10 章)第 1199–1211 段(text/28-fm-introduction.txt:1208,搜「20 minutes」;text/28-fm-introduction.txt:1211,搜「developer productivity」)。 ↩

  27. 出处:「Introduction」(第 10 章)第 1220–1253 段(text/28-fm-introduction.txt:1223,搜「Latency > 300 ms」;text/28-fm-introduction.txt:1229,搜「baseline patterns」;text/28-fm-introduction.txt:1247,搜「Synthetic monitoring」)。 ↩

  28. 出处:「Introduction」(第 10 章)第 1256–1385 段(text/28-fm-introduction.txt:1305,搜「Reduce below 5 minutes」;text/28-fm-introduction.txt:1341,搜「80%」;text/28-fm-introduction.txt:1377,搜「under 10%」)。 ↩

  29. 出处:「Introduction」(第 10 章)第 1388–1397 段(text/28-fm-introduction.txt:1394,搜「every minute」;text/28-fm-introduction.txt:1397,搜「under three」)。 ↩