系统是被打出来的 · 系统设计实战手册
PART 4 · 高可用与多活 · 第 14 章

可观测性
看懂凌晨三点的仪表盘

监控不是把图表铺满墙,而是让你从用户症状一路追到因果证据。凌晨三点,系统整体慢了 15%,没有发布、没有报错、没有一块面板变红——这才是观测能力的考试。

14 · 1 值班现场03:00,什么都没改,系统却慢了 15%

创业第 5 年 3 个月,「秒抢」累计用户约 4000 万,公司 280 人,研发 70 人。你刚接过本周 on-call,03:00 收到一条不够红、却让人无法继续睡的告警:全站核心旅程 P99 比过去七天同一时段慢了 15%。

PagerDuty · SEV-2 · 触发于 03:00:06
[WARNING] checkout journey P99 1.38s(7d 同时段基线 1.20s,+15%)
[INFO]     request rate 18,200/s,error rate 0.21%(均在基线)
[INFO]     最近 6 小时业务服务发布 0
──────────────────────────────────────
值班群第一条回复:
「CPU、内存、探活都绿,可能只是夜间流量抖动?」

你把用户症状与资源面板对齐。Rate 和 Errors 没变,Duration 的退化却跨订单、库存、支付三个服务同步出现;单看平均值,几乎看不出问题:

核心旅程 P50
412ms
● 基线 395ms,+4%
核心旅程 P99
1.38s
▲ 基线 1.20s,+15%
服务 CPU
37%
● 基线附近
出站连接池排队
P99 186ms
▲ 基线 12ms

没有业务发布,不等于运行环境没有变化。03:00 前后,三个服务的自身处理时间都稳定,慢掉的 180ms 集中出现在它们访问内部服务的出站等待上。探活请求不走这条高并发连接池,所以每个实例仍报告健康。

阿凯查到平台层在 02:55 做过例行配置重载:服务网格代理重启后,出站连接池从显式 512 回落到默认 64。总流量不变,连接利用率却从 43% 推到 92%,少量请求开始排队;它没有制造错误,只把每段远程调用都拉长一点。

决策点 D1

此刻是 03:04。你先做哪一步来确认方向?

B 是教科书答案:先比较慢在哪里,再解释为什么。正常与慢 trace 的差分能把十几个服务缩成共同增长的出站等待 span;随后看连接池利用率、饱和度和错误,证据会指向共享代理而不是三个业务进程。

A 会破坏证据,还可能放大抖动。三个服务同时重启会清空本地连接与缓存,制造新的冷启动峰;即使暂时恢复,也无法证明根因。CPU 与自身处理时间稳定,重启没有对应假设。

C 没有可回滚对象。「线上慢了就回滚」是有效本能,但必须先确认时间线上存在变更。业务发布为零时强行回滚旧版本,只会引入另一个变量,平台配置仍原地不动。

D 让告警安静,却没有让用户变快。阈值调整适合修正错误目标;本次 15% 退化已由七天基线与 trace 共同证明。先修连接池,再评估告警是否过敏。

14 · 2 原理从症状到位置,再到原因

「metrics 告诉你坏了,traces 告诉你哪坏了,logs 告诉你为什么坏。」三者不是互相竞争的工具:指标适合低成本覆盖和趋势告警,链路适合还原一次请求穿过哪些边,日志适合解释某个组件在那个时刻做了什么决定。

metrics:用户旅程 P99 +15%
traces:共同变慢的 span = outbound_pool_wait
logs:02:55 配置重载,pool_size 512 → 64

把现场代入这条路径:指标先证明不是主观感受;抽取 200 条慢 trace 与 200 条同路由正常 trace,发现业务 span 中位差异不足 8ms,出站池等待却多出约 175ms;代理日志再给出配置回退时间和值。三个证据互相校验,形成可执行根因,而不是一句「网络可能有问题」。

RED 看服务,USE 看资源

方法 维度 它回答什么 本次现场
RED
面向服务
Rate 请求量是否改变 18,200/s,基线附近
Errors 失败比例是否改变 0.21%,基线附近
Duration 延迟分布是否改变 P99 +15%,症状成立
USE
面向资源
Utilization 资源忙碌比例多高 出站连接利用率 92%
Saturation 还有多少工作在排队 池等待 P99 186ms
Errors 资源层拒绝或失败多少 接近零,尚未变成失败

这正是为什么只看 CPU 容易漏诊。连接池是一种资源,它的利用率和饱和度可以在 CPU 37% 时先出问题。USE 中最早发声的往往是 Saturation:队列、等待线程、pending I/O;等错误率上升,用户已经替系统等了一段时间。

可观测性不是采集更多数据,而是让每个用户症状都能沿同一个业务标识,依次落到服务边、资源队列和组件决策上。

先建问题树,再开查询框

面对「线上变慢」,不要先在日志平台搜索 error。可以按一棵稳定的问题树推进:

问题 证据 下一步分支
用户真的慢了吗 端到端 P50/P95/P99、成功率、地区与版本切片 若只影响一类用户,先按维度缩小;若全局,再看服务 RED
慢在哪一段 正常与慢 trace 差分、关键 span 占比 自身处理慢看进程;远程等待慢看依赖与网络
资源是否排队 线程、连接、CPU、磁盘、队列的 USE 高利用无排队可观察;出现饱和要先降载或扩容
为什么从这个时刻开始 发布、配置、流量、依赖、证书与计划任务时间线 用日志和审计记录验证变更,不靠记忆猜

每走一步都要能排除一个分支。本次 Rate 与 Errors 稳定,排除流量洪峰和显性失败;trace 指向共同出站等待,排除三套业务逻辑同时退化;USE 显示连接池饱和,审计日志又与 02:55 配置重载对齐。证据链越短,止血动作越小。

高基数不是免费午餐

为了切片,你会想把 user_id、order_id、URL、错误文本都塞进指标标签。指标系统却需要为每种标签组合维护时间序列:100 个服务 × 20 个状态 × 4000 万用户,不是更多洞察,而是不可控的基数。稳定、有限的维度放 metrics;订单级标识放 traces 和 logs,通过 exemplar 或 trace id 连接。

采样也要按问题设计。均匀采 1% 可能漏掉低频错误;更实用的是保留 100% 错误与超慢 trace,再对正常流量低比例采样。若某故障只占 0.05%,均匀采样 1% 每百万请求只留下约 5 条故障 trace,排障证据会非常稀薄。

症状告警与原因告警

症状告警从用户承诺出发:成功率、延迟、正确性、积压年龄是否违反 SLO。它适合叫醒人,因为影响已经成立。原因告警监控 CPU、连接池、磁盘、证书到期等内部条件,适合自动化处置、工单或作为排障上下文;不是每次资源抖动都值得凌晨叫人。

信号 告警类型 推荐路由 理由
支付成功率跌破 SLO 症状 立即 page 用户影响已发生,需要值班处置
订单 P99 持续超预算 症状 按 burn rate page 避免单个毛刺,也不等到月末耗尽预算
CPU 75% 持续 10 分钟 原因 自动扩容或工单 用户可能尚未受影响,先让系统自愈
证书 14 天后过期 原因 工单 + 逐级升级 有处理窗口,不应立即叫醒值班人

告警疲劳也能算

假设一个值班团队每天收到 120 条 page,其中只有 3 条需要人工立即动作,剩下 117 条是噪音。告警精度是 3 ÷ 120 = 2.5%;按每条确认与切换上下文 3 分钟算,每天消耗约 351 分钟,接近 6 小时。

每日 page
120
其中噪音 117
可行动比例
2.5%
3 ÷ 120
每日噪音成本
约 351min
117 × 3 分钟
月度噪音
3,510 条
按 30 天计算

因此 每天噪音告警 N 条 → 响应意愿衰减 不是心理鸡汤。值班人被训练出「大概率无需动作」的先验后,真正告警也会先被怀疑。治理顺序是:删掉无 runbook 的 page;合并同一根因的风暴;把原因告警降为工单;用 SLO burn rate 同时看影响幅度与持续时间;每次事件复盘告警是否早、准、可行动。

第 16 章的混沌实验会反过来验证这些观测:注入故障后,症状告警是否先于用户工单,trace 是否指向注入点,自动回滚是否在爆炸半径扩大前触发。没有被演练过的仪表盘,只能证明数据被采集,不能证明团队会使用。

14 · 3 病历卡形状是压缩过的故障叙事

本章不新增病历卡。可观测性的任务,是让前面章节的病在大盘上保留可辨认形状,并能从形状跳到具体请求与资源。

病历卡 No.15灰色故障▇▇▇▇ 部分实例、分区或请求持续失败,探活与聚合平均值却保持正常;必须按维度切片并保留慢请求 trace。附录病历卡图鉴 →
病历卡 No.07重试风暴▁▂▄█████ Rate 自持续爬升、下游 Errors 与 Duration 同步恶化;trace 会出现同一业务意图的重复 span。第 7 章定义 →
病历卡 No.11消息积压▁▂▃▄▅▆▇ backlog 与 oldest age 单调上涨,生产和消费都可能健康;要比较两条速率线,而不是只看组件存活。第 9 章定义 →

三种形状分别提醒你:平坦不代表健康、增长可能是反馈回路、增长也可能只是净速率为正。形状负责给第一假设,traces 和 logs 负责证伪;不要拿图形相似替代根因证据。

14 · 5 权衡告警宁敏感,还是宁安静

漏报会让用户先发现事故,噪音会让值班人逐渐不相信系统。阈值不是越低或越高越专业,它要匹配影响代价、自动恢复能力和人工动作。每一个都是对的,每一个都有账单。

决策点 D2

核心下单旅程的告警策略怎么定?

A · 宁敏感:小范围故障更早被人看见,适合支付、库存等漏报代价高的链路。账单:短毛刺和自动恢复会频繁叫醒值班人,长期降低信任;必须配合去抖、合并和明确 runbook。适合低频高损、人工能快速止损的信号。

B · 宁安静:page 数量低,值班人更愿意相信每次呼叫,调查质量也更高。账单:小范围灰色故障和缓慢退化可能等到用户工单才暴露。适合可自动恢复、影响低或有白天处理窗口的原因信号。

C · 多窗口 burn rate:用错误预算消耗速度同时衡量幅度与持续时间,快故障和慢性病走不同通道。账单:需要可靠 SLO、基线和演练,规则比单阈值复杂;错误预算定义错了,精致算法也会路由错误。适合已有端到端 SLI 的核心旅程。

「秒抢」的选择:核心下单采用 C,高 burn rate 立即 page,低 burn rate 建事件并在白天跟进;库存正确性与支付丢单另设低容忍症状告警。CPU、连接池等原因信号优先驱动自动扩容和排障上下文,不直接制造同等级 page。

14 · 6 复盘那 15% 后来怎么被定位到 64 个连接

回放 03:00 的正确剧本——每一步都缩小假设空间,没有用重启替代证据:

03:04

确认用户症状。按路由、地区和版本切片,确认 P99 +15% 跨三个核心服务存在,Rate 与 Errors 稳定;事件不是流量毛刺,也不是单客户端版本。

03:09

比较 trace。200 条慢请求相对正常请求共同多出约 175ms 的 outbound_pool_wait,业务处理 span 基本不变,调查从三个服务收敛到共享代理。

03:14

用 USE 解释。连接池利用率 92%、排队 P99 186ms、错误接近零;审计日志显示 02:55 重载后 pool_size 从 512 回到 64,时间与退化对齐。

03:22

小范围恢复并验证。先在一个单元恢复 512,P99 回到 1.19s;随后分批推广,端到端指标恢复基线。团队补上配置漂移检测和重载后的合成交易。

壹
从用户症状开始,不从机器猜起。端到端 SLI 先证明影响,再用 RED、trace、USE 和日志逐层缩小;绿 CPU 不能否定慢用户。
贰
「没有发布」不是「没有变化」。配置重载、证书、流量、数据分布与依赖状态都在改变;时间线要覆盖代码之外的运行环境。
叁
每条 page 都要购买一个动作。叫醒人却没有影响定义、owner 和 runbook 的告警,会用噪音透支下一次真正事故的响应意愿。

14 · 7 自测你能把三支柱串成证据链吗

Q1 · 看形状诊断

大盘显示 ▁▂▄█████:请求 Rate 自持续上涨,下游 Duration 与 Errors 同步恶化,trace 中同一业务键出现多次调用。最可能是哪类故障?

A。自持续 Rate、错误恶化和同键重复调用共同指向重试反馈回路。B 也会爬升,但主要是 backlog 与 oldest age,生产请求不必被重复放大;D 无法解释同一业务键的重复 span 与下游错误同步上升。

Q2 · 告警疲劳算术

每天 120 条 page,只有 3 条需要立即人工动作。可行动比例是多少?若每条噪音耗 3 分钟,每天噪音成本约多少?

A。3 ÷ 120 = 2.5%;噪音 117 条,117 × 3 = 351 分钟。C 把噪音比例当成可行动比例;D 又把每条告警只算 1 分钟。低精度会真实占用注意力,而不只是让列表难看。

Q3 · RED 与 USE

请求量和错误率稳定,P99 上升;CPU 低,但连接池 pending 与等待时间很高。最准确的判断是?

B。服务延迟退化已由 RED 证明,资源排队由 USE 的 Saturation 解释。A 把 CPU 当成资源总表,忽略连接这种独立资源;C 会等到排队演变成超时才承认影响;D 可能增加 I/O,却没有先建立假设。

Q4 · 三支柱分工

以下哪条排障链最符合本章方法?

B。三支柱沿症状、位置、原因逐级缩小。A 的搜索没有用户范围和时间假设;C 会淹没在细节里且缺少趋势,D 能看见退化却难定位跨服务边。它们不是替代品,而是可关联的证据层。

🎯 面试映射 · 本章直接覆盖的高频追问

「线上整体变慢,怎么定位?」 答题骨架:端到端 SLI 确认影响 → 按用户/路由/版本切片 → RED 找服务 → 正常/慢 trace 差分 → USE 找饱和资源 → logs 与变更时间线验证 → 小范围恢复。
「怎么设计告警不被淹没?」 答题骨架:症状告警 page、原因告警自动化/工单 → SLO burn rate 多窗口 → 去重合并 → owner + runbook → 定期统计精度、响应时间和噪音成本。
「metrics、traces、logs 各解决什么问题?」 答题骨架:metrics 看覆盖与趋势 → traces 还原单次跨服务路径 → logs 解释局部决策 → 用 trace id/exemplar 关联。反直觉加分点:数据量最多的支柱不自动拥有最高诊断价值。