专业书籍精读 · SRE · 第 6 章
Site Reliability Engineering · Ch 6 · Google(Rob Ewaschuk)· 2016
你半夜下单付款失败,第二天它又好了——中间多半有个人被电话叫醒过。这一章讲的就是那通电话该在什么时候打:一套线上服务要盯哪些数、什么情况算「坏了」、什么情况值得把一个大活人从床上拽起来。
把它想成家里的烟雾报警器。你会装几个?装一个,厨房着火时它响,你信它。装二十个、还调得极其灵敏,那么每次炒个菜、洗个热水澡它都叫——不出一个月,你就会把电池全抠掉。到那天,真着火了也没人管。这一章从头到尾在防的就是这个结局:报警器多到没人信,比没有报警器更危险。
大多数人以为这活的方向是「越聪明越好」——最好有个系统自动看出「哪里坏了、为什么坏」,人只管等结论。Google 说他们试过,然后主动放弃了。理由很朴素:越聪明的系统内部越绕,真出事的时候,你得先花半小时搞清楚它为什么这么说,而你本来只有五分钟。他们最后选了个听上去很没出息的方向——又笨又快。
一套服务能量的东西成千上万,真正该一直盯着的只有四件,就像看一家餐厅只需要看:上菜要等多久、今天来了多少客人、上错了多少盘、后厨还剩多少余地。前三件说的是「现在怎么样」,第四件是唯一能提前报信的——后厨快转不动了,你还来得及加人;等菜真端不出来就晚了。
这里有个特别容易栽的坑:算「上菜多久」时,要把上错的单子单独算。因为店一崩,它拒绝接单是很快的——「对不起做不了」两秒就能说完。混在一起算,数字反而显示今天上菜特别快:看着一片大好,其实店已经塌了。
知道哪里不对,和把人叫醒,是两件事。这章给的门槛几乎苛刻:能把人从床上叫起来的事,必须同时满足三条——真的急、真的有事可做、而且非得靠人的判断不可。最后那条最狠:如果你被叫醒之后的全部动作,就是照着一张纸点几下,那这件事根本不该叫人,应该让机器去点。人被叫醒是因为需要一个脑子,不是需要一双手。
顺着这条门槛,事情自然分三档:需要现在就有人来的,打电话;需要人做但不急的,开张单子几天内办掉;谁也不用看的,写进日志躺着——真出事那天,它是唯一能还原现场的东西。
诚实的代价:这套做法会让你在故障刚起时知道「坏了」,却一时说不清「哪坏了」——所以内部的详细数据一个都不能少,只是不许它们打电话叫人。
盯四件事就够:多慢、多忙、错多少、多满(只有最后一件能提前报信)。而叫醒一个人的门槛是:急、有事可做、且非人不可——凡是照着流程点几下就完事的,交给机器。报警器一多,人就不信了,这比没有报警器更糟。
想进到具体机制、数字和示意图? → 切到精读版
你以为监控(monitoring)这一章教你「多收集指标」,其实它整章都在做减法:Google 明确放弃了「能自动学阈值、自动推根因」的智能监控,转而要求监控系统简单、快、可预测;把用户可感知的四个黄金信号(four golden signals)——延迟、流量、错误、饱和度——立为最小充分集;并给页面告警(page,会把人立刻叫醒的那种通知)划下一条近乎苛刻的门槛:每一次寻呼都必须紧急、可行动、且需要人的判断;只要它的处置是机械的,就该交给机器,而不是叫醒一个人。
p99 就是「一百个请求里最慢的那一个」。直方图(histogram):把观测值按区间分桶计数,得到分布而非一个平均数。作者 Rob Ewaschuk,本章脱胎于他在 Google 内部流传甚广的一篇文章《我的告警哲学》(My Philosophy on Alerting)。这是全书 Part II「原则」的收尾章:第 3 章教你用错误预算给可靠性定价、第 4 章教你把目标写成 SLO、第 5 章教你把琐务砍掉——而这一章回答「那你到底该盯什么、什么时候该叫人」。它下启 Part III 的实践篇:第 11 章的 on-call 值班、第 12 章的有效排障,都建立在「告警是干净的」这个前提上。落到现实,它对应的就是今天每个团队的 Prometheus / Grafana 面板与 PagerDuty 值班表。
「多监控点总没坏处」是行业里最贵的一句错话。一套服务能导出的指标轻易上万条,每条都能配个阈值告警,每加一条团队都觉得更安全了一点。真实结果是:值班手机一夜响十几次,其中十二次不需要任何人做任何事。三个月后,值班的人练出了「看一眼、划掉、接着睡」的肌肉记忆——那条真的告警混在里面,也被划掉了。这一章要解决的正是这个:不是「怎么监控得更多」,而是「怎么让每一次叫醒都值得」。
它同时防另一头:只在用户投诉时才知道出事(监控不足)。但书里有句很硬的判断:过度监控比监控不足更难解决——因为前者要修的是人对系统的信任,那东西建起来慢、塌下去快。书里给的人力量级也说明这活不轻:一个十来人的 SRE 团队里,通常有一两个人的时间花在建设和维护监控上。
本章开篇把监控的用途摊开:分析长期趋势、跨时间或跨实验组比较、告警、做面板、做临时的回溯分析。五类里只有「告警」会消耗人的睡眠——这个区分是整章的地基:面板铺得再花、指标留得再多、日志存得再久,都不打扰人;但一条规则一旦接到寻呼上,它就开始花钱了,花的是值班工程师的注意力。与之配套的是一条常被忽略的原则:监控系统不该要求人去「解读」它——解读由软件做完,人只在需要采取行动时被通知。一个要人盯着面板判断「这抖动算不算事」的系统,本身就是设计失败。
本章把监控要回答的问题拆成两半:症状(symptom)——什么坏了;原因(cause)——为什么坏。书里的例子很直白:症状是「我在返回 HTTP 500 和 404」,原因可能是「数据库服务器拒绝连接」;症状甚至可以是「南极洲的用户收不到动图了」,而原因是内容分发网络(CDN)把某段客户端 IP 拉黑了。
结论是告警只该报症状:症状是用户真在受的苦,而原因有一百种、且经常猜错。原因去面板和白盒指标里找——等人被症状叫来以后,用它们把原因挖出来。还有个漂亮的观察:多层系统里,一个人的症状就是另一个人的原因。「数据库变慢」对 DBA 是症状,对调它的前端服务就是原因。所以症状 / 原因不是绝对标签,而是相对于你负责的那一层。
白盒监控看系统内部主动暴露的东西:HTTP 处理器导出的计数器、日志、运行时统计。它的独门本事是看见「被掩盖的问题」和「即将发生的问题」——请求靠重试成功了,用户没感觉,但重试率已经翻了十倍;磁盘还没满,但按当前增速四小时后会满。
黑盒监控从外部像用户一样发请求,是症状导向的:它报的一定是此刻真的在发生的问题,而不是「可能要出事」——所以它天生适合接寻呼,一响就说明现在真有人在受苦。
Google 的取舍因此很明确:页面告警重度依赖黑盒,加上少量症状导向的白盒规则;白盒的大头拿去做面板与调试。反过来说,若你的寻呼绝大部分接的是白盒内部指标(CPU 高了、队列长了、某进程重启了),那你多半正被叫醒去处理一堆用户根本没察觉的事。
本章最广为流传的部分:如果你只能量四个指标,量这四个——延迟、流量、错误、饱和度。书里的承诺相当直接:把这四个都量上,并在任一个出问题(饱和度是「快出问题」)时叫人,你的服务在监控上至少算过得去了。
延迟(latency):处理一个请求要多久。这里藏着本章最反直觉的一条:必须把成功请求与失败请求的延迟分开统计。因为一个丢了数据库连接的服务,返回 HTTP 500 是飞快的——几毫秒就能说完「我不行」。混在一起算,故障最严重的那几分钟,面板上的平均延迟反而会变好看。书里还有一句常被引用的话:慢的错误比快的错误更糟,所以失败请求的延迟也得单独盯。
流量(traffic):用「系统正承受多少需求」度量,单位要贴着业务。Web 服务通常是每秒 HTTP 请求数,还要按性质拆开(静态资源 vs 动态接口,成本差一个量级);音频流媒体是网络 I/O 速率或并发会话数;键值存储是每秒事务数与检索数。
错误(errors):失败请求的比率,三种形态——显式(返回 500)、隐式(返回 200,但内容是错的)、按策略(你承诺一秒内响应,那么 1.2 秒才成功的请求按定义也算错)。隐式错误最难抓,往往要端到端校验内容才发现——而它恰恰最伤用户信任。
饱和度(saturation):系统「有多满」,重点盯最受限的那个资源。它是四个信号里唯一带预测性的,三条要点:① 很多系统在利用率到 100% 之前就开始退化,所以要设利用率目标,别等它满;② 延迟上升往往是饱和度的先行指标——用很短的窗口(比如一分钟)看 p99 延迟,常能在资源真告急前看见苗头;③ 它还要能回答「照这个速度,你的数据库四小时后写满磁盘」这类预测。
本章专门拎出一节讲尾部:把「平均耗时 100 毫秒」和「99% 的请求 10 毫秒、1% 的请求卡 5 秒」混为一谈,是最常犯的统计错误——平均值可能一样,用户体验天差地别。平均值是双峰分布的谎言。
对策不是多算几个百分位,而是改变采集方式:别在服务端算一个平均数报上来,要按耗时把请求分桶计数——0–10ms、10–30ms、30–100ms、100–300ms……边界大致按指数增长。这样上报的是一个分布,任何百分位都能事后算出来,多台机器的桶还能直接相加。这就是今天 Prometheus 里 histogram 的由来。
分辨率是另一场权衡:采得越密信号越全,但采集、传输、存储、查询的成本全跟着涨。本章给了很具体的量级——一个目标为 99.9% 年可用性(全年累计不可用不超过 9 小时)的 Web 服务,用黑盒探测看返回码,每分钟一到两次通常就够;查磁盘占用率,一到两分钟一次也够。再密就是白花钱。
但反过来,CPU 这类指标一分钟一个点会漏掉真相:那些持续几秒、足以把尾延迟顶上去的尖峰,在一分钟的平均里根本看不见。书里的解法很巧:内部高频采样、就地聚合,再低频上报——每秒记一次 CPU 利用率,按 5% 粒度分桶累加,每分钟把整个桶的分布报出去一次。你拿到了每秒级的分辨率,只付了每分钟一次的传输与存储成本。
本章最后落在一条价值观上:监控系统要尽可能简单,但不能再简单。压力来自四面八方——想抓越来越罕见的异常、想加更多信号源、想让它自己推断根因……堆着堆着,监控系统本身就成了一个要专人维护、出事没人敢碰的复杂系统。书里的三条减法判据非常好用:
这也解释了 Google 那个看似「没出息」的选择:他们刻意避开试图自动学习阈值、自动推断因果的「魔法」监控系统。理由很实在——真出事的时候,你得先调试这个魔法系统自己的判断,而事故现场没有这个时间。他们的经验是:简单、快的监控 + 好用的事后分析工具,比一个聪明但难懂的系统管用得多。
表 1 · 黑盒 vs 白盒:什么时候用哪个
| 黑盒监控 black-box | 白盒监控 white-box | |
|---|---|---|
| 视角 | 从系统外部像用户一样发请求 | 系统内部主动导出的计数器 / 日志 / 统计 |
| 回答 | 什么坏了(症状) | 为什么坏(原因),以及即将坏 |
| 时态 | 只报此刻正在发生的问题 | 能看见被重试掩盖的失败、能预测(如「4 小时后磁盘写满」) |
| 接寻呼? | 是——页面告警的主力 | 只接极少数症状导向的规则;其余进面板 |
| 代价 | 知道「坏了」但说不清哪坏了;探测本身也可能误报 | 「内部不对劲」绝大多数时候用户毫无感觉,接寻呼就是噪声源 |
表 2 · 四个黄金信号:怎么量、量在哪、坑在哪
| 信号 | 量什么 | 典型度量 | 最常踩的坑 |
|---|---|---|---|
| 延迟 latency | 处理一个请求要多久 | 分桶直方图 → p50/p95/p99;成功与失败分开 | 把失败混进来算:崩溃时快速返回 500,反而让平均延迟「变好看」 |
| 流量 traffic | 系统正承受多少需求 | 每秒请求数(静态 / 动态拆开);流媒体看网络 I/O 或并发会话;KV 存储看每秒事务与检索 | 用一个笼统的 QPS 盖住成本差一个量级的不同请求 |
| 错误 errors | 失败请求的比率 | 显式(500)/ 隐式(200 但内容是错的)/ 按策略(承诺 1 秒,1.2 秒也算错) | 只统计显式错误;隐式错误最伤信任却最难发现 |
| 饱和度 saturation | 最受限的资源还剩多少 | 内存 / I/O / CPU 的利用率与余量;短窗口 p99 延迟作为先行指标;「几小时后写满」的预测 | 等到 100% 才报警——多数系统在满之前就已经开始退化 |
表 3 · 一条规则该输出到哪一档
| 输出 | 判据 | 响应时限 | 典型例子 |
|---|---|---|---|
| 页面告警 page | 紧急 + 可行动 + 需要人的判断(三条同时成立) | 立刻 | 面向用户的错误率突破 SLO、服务整体不可达 |
| 工单 ticket | 需要人做事,但今晚不做也不会更糟 | 数天内 | 某副本容量吃紧、证书三周后过期 |
| 日志 logging | 不需要任何人主动看 | 事后回溯才用 | 逐请求明细、调试用的内部状态 |
| 什么都不做 | 处置是机械的、可脚本化的 | — | 写成自动化,别接寻呼——人被叫醒是因为需要脑子,不是需要一双手 |
本章还给了一份「这条告警该不该存在」的自查清单,值得贴在每个团队的墙上:
配套的态度也很鲜明:寻呼应当紧急、重要、可行动、且需要智力参与;每次寻呼最好指向一个新问题,而不是同一个老毛病第 40 次发作。宁可失手删掉一条吵闹的告警——过度监控比监控不足更难解决。
这一章的影响力大概是整本 SRE 书里最外溢的:「四个黄金信号」已经成了监控领域的通用语言。今天你打开 Grafana 的服务模板面板、Kubernetes 的默认监控、Istio 之类服务网格自动生成的指标、或 Datadog / New Relic 的服务概览页,骨架基本都是这四个信号的变体;histogram 成为 Prometheus 的一等公民,也直接源于本章「别报平均值、要报分布」的主张。它还长出两个广为流传的「方言」:RED(Rate 请求率 / Errors 错误 / Duration 耗时)是四信号在请求驱动服务上的裁剪版,砍掉了饱和度;USE(Utilization 利用率 / Saturation 饱和度 / Errors 错误)是资源侧的对偶。业界常见搭配是RED 管服务、USE 管机器,合起来正好把四个黄金信号覆盖完整。
面试里,这一章是「监控 / 可观测性」题的标准答案来源:告警该基于症状还是原因?(症状,原因有一百种且经常猜错)为什么不能只看平均延迟?(平均值是双峰分布的谎言,要看分布与尾部)成功和失败的延迟为什么要分开算?(失败返回得飞快,混在一起会让故障看起来像性能改善)——这三问答得清楚,基本就说明你读懂了这一章。
99.9% 的 SLO,用 1 小时窗口、14.4 倍燃尽率(1 小时烧掉 2% 错误预算)触发寻呼,用 6 小时窗口、6 倍燃尽率(6 小时烧掉 5%)触发较缓的告警。这是对本章阈值告警范式最权威的一次升级。The SRE Workbook「Alerting on SLOs」, 2018 ↗p99 再取平均——百分位不可加,正确做法是把各机器的分桶计数相加后再算百分位(这正是上报分布而非单值的直接好处)。① 一句话:这一章讲的是减法——不是怎么监控得更多,而是怎么让每一次叫醒都值得。
② 监控有五类用途(趋势、比较、告警、面板、回溯分析),只有「告警」会花掉人的睡眠;且监控系统不该要求人去解读它。
③ 告警报症状、面板答原因;多层系统里,一个人的症状就是另一个人的原因。黑盒用来叫人(一响就说明现在真有人在受苦),白盒用来查因和预测。
④ 四个黄金信号:延迟、流量、错误、饱和度。都量上、任一出问题就叫人,监控覆盖就算过得去。饱和度是唯一的先行指标,且多数系统不到 100% 就开始退化。
⑤ 最反直觉的一条:成功与失败的延迟必须分开算——失败返回得飞快,混在一起会让重大故障看起来像性能改善;而慢的错误比快的错误更糟。
⑥ 别报平均值,报分布:按耗时分桶(边界大致指数增长)上报直方图,百分位事后再算,多机的桶还能直接相加。
⑦ 分辨率是成本权衡:99.9% 可用性的服务,返回码探测每分钟一两次就够;但 CPU 要靠「内部每秒采样、按 5% 粒度分桶、每分钟上报一次」拿到高分辨率而不付高成本。
⑧ 减法三判据:主力规则要简单可预测;一个季度用不到一次的配置该删;采了却不上面板、不进告警的信号该删。Google 刻意避开「能自动推根因」的魔法系统——出事时你没空调试它。
⑨ 叫醒人的门槛:紧急 + 可行动 + 需要人的判断。处置是机械的,就交给机器。宁可删掉吵闹的告警——过度监控比监控不足更难解决。