故障表象很会骗人,先抓那条最先失真的证据

保留下来的几个场景,都在逼人修正同一种错法:拿最顺眼的指标抢答,结果越查越偏。

本页目录

故障表象很会骗人,先抓那条最先失真的证据

线上系统一慢,团队最容易做的事不是分析,而是抢答。有人盯住 CPU,有人盯住磁盘,有人先开 perf。Gregg 留下来的案例价值,就在这里:它们不断提醒你,最先跳出来的表象,往往不是最该相信的证据。

CPU 看着不高,延迟已经塌了

调用信号很明显。用户已经感到慢,服务的平均 CPU 却不吓人,监控面板上看不到一个足以直接定案的红点。

这时最容易犯的错,是把“CPU 不高”翻译成“系统层没问题”,然后一头扎进应用日志或业务代码。可真正卡住请求的,常常不是算得慢,而是等得久。线程在等锁,等 I/O,等调度,等下游,CPU 面板当然不会替你把这些时间说出来。

Gregg 在这里给的切入口,不是继续追平均利用率,而是先拆时间去向。on-CPU 是线程真正占着处理器在跑;off-CPU 是线程没在跑,但请求时间照样在流失。把这两块分开,排障路径才会转正。

这个场景最适合当团队校准题。以后再看到“系统慢但 CPU 正常”,第一反应不该是排除系统层,而该是问一句:时间到底花在执行,还是花在等待?

吞吐一上不去,先问谁在排队

另一类高频现场,是流量刚上来,尾延迟先拉长,吞吐却没有同步抬上去。许多团队会立刻把答案写成“机器不够,先扩容”。

扩容有时对,但不能抢在判断前面。Gregg 更在意的,是哪一种资源先进入饱和。利用率描述资源忙不忙,饱和度描述请求有没有开始排队。系统真正开始发抖,经常不是在 100% 利用率那一刻,而是在排队先失控的那一刻。

所以这类案例最该留下来的,不是“高峰期要留余量”,而是 USE 的调用顺序。CPU、内存、磁盘、网络逐项过;每项都看利用率、饱和度、错误。谁先排队,谁才是往下钻的入口。

如果跳过这一步,扩容很可能只是把瓶颈从一个资源域搬到另一个资源域。图表变了,根因没变。

火焰图很漂亮,结论却可能跑偏

熟悉 perf 和火焰图的团队,常见另一种误判:图上最宽的栈就是最该优化的地方。

这条判断只在一个前提下成立——那个热点确实主导了端到端延迟。可很多请求真正耗时的部分不在 on-CPU,而在等待磁盘、等待网络、等待锁释放。热点函数改薄了,用户体感却没什么变化,问题就出在“CPU 热点”和“延迟主因”被混成了一件事。

Gregg 在工具章节反复拉开的边界,正好能修这个错。profile 回答的是“处理器时间花在哪”;它不自动回答“请求为什么慢”。当问题定义还是端到端延迟时,采样结果必须放回整条请求路径里解释,不能单独判案。

这个案例的意义,不在于反对火焰图,而在于提醒团队先问工具在回答哪类问题。问题问错了,图越漂亮,误判越快。

云上什么都像正常,其实证据已经断层

进入云环境后,最难受的不是问题更多,而是能直接摸到的证据更少。实例内 CPU、内存、磁盘看上去都还能接受,应用日志也没报错,但 P99 延迟就是突然坏掉。

单机经验到了这里很容易失灵。你看不到宿主机,看不到邻居噪声,也摸不到很多底层细节。继续沿着裸机那套证据链硬查,常常会在“每个点都不够异常”里打转。

Gregg 第二版最有用的补丁,就是教你改用边界证据。看 steal time,判断 CPU 是否被宿主机拿走;看同服务实例之间是否分化,判断问题是全局还是局部;看可用区对比和版本前后对比,判断异常是不是和部署、区域、资源池有关。

这些证据单看都不算硬。但当你已经失去完整视角,它们足以先把范围钉住。云上排障最怕的不是证据不完美,而是还在等一份根本拿不到的完美证据。

指标降下来了,不等于方法已经留下来

还有一种场景,不发生在故障现场,而发生在故障之后。延迟降了,错误率回来了,团队松一口气,复盘却写不出一句能复用的话。

这时缺的不是结果,而是因果。到底解除的是什么约束?哪条证据把判断锁住了?有没有副作用?下次看到什么信号时,可以直接复用这条路径?

Gregg 真正在意的,是把一次成功优化变成下一次能少走弯路的经验。如果复盘只剩“改完之后快了 40%”,那只是留下结果,没有留下方法。

所以这个案例要提醒的,不是复盘要写得更完整,而是 before/after、约束定位、验证方式和副作用评估必须连成一条链。链没立住,优化只是碰巧成功;链立住了,团队才算真的学会一次。

同分类继续看