1. 故障复现的哲学
做故障排查这么多年,我见过太多人一上来就翻日志、查监控、改代码。忙活半天,问题没找到,反而把现场搞乱了。你想想看,这像不像一个侦探到了案发现场,二话不说先把脚印擦了?
故障复现,就是那个「保护现场」的动作。它不是什么高深理论,而是整个排查工作的地基。地基不稳,后面全是白搭。
为什么非要复现?
说白了,不复现的排查就是瞎猜。我遇到过不少团队,线上出了故障,看一眼错误日志就断定是「内存泄漏」,然后开始加参数、改配置。结果呢?问题照旧。为什么?因为那个日志可能是另一个无关问题留下的。
复现能帮你做到三件事:
- 确认问题真实存在——有些告警是误报,有些是偶发,不亲手复现一次,你连对手是谁都不知道。
- 锁定触发条件——同样的代码,为什么今天崩明天不崩?复现能让你找到那个「开关」。
- 验证修复是否有效——改完代码,跑一遍复现步骤,问题没了,这才叫修好了。否则你只是在赌。
核心观点:不复原,不诊断。这是故障排查的第一条铁律。
复现的三大原则
我这些年总结下来,好的复现流程必须满足三个条件:可观测、可控制、可重复。缺一个,复现就是白做。
1. 可观测(Observable)
复现过程中,你得能「看见」故障的发生。看不见,就等于没发生。
什么叫可观测?我举个例子。有一次线上服务频繁超时,我让团队先加全链路追踪,把每个接口的耗时、调用栈、数据库查询都打出来。然后才去复现。结果发现,超时都卡在同一个 Redis 操作上——那个操作没设置超时时间,连接池被占满了。
如果没有这些观测手段,你只能看到「服务慢」,根本不知道慢在哪。
可观测的手段包括:
- 日志——结构化、带时间戳、分级别
- 指标——CPU、内存、QPS、延迟分位数
- 链路追踪——一次请求经过的所有服务节点
- 事件记录——配置变更、发布、回滚等操作
我的习惯:在复现之前,先问自己一句——「如果故障发生了,我能不能从数据里看出它从哪开始?」如果答案是否定的,先补观测手段,再动手复现。
2. 可控制(Controllable)
复现不是碰运气。你得能主动控制环境、流量、数据,让故障按你的意愿出现。
我记得有一次排查一个内存泄漏问题。线上环境 8 小时才触发一次,根本没法调试。后来我写了个压测脚本,把请求量放大 10 倍,同时把 GC 日志打开。结果 20 分钟就复现了。为什么?因为我控制了流量和观测开关。
可控制的关键要素:
| 控制维度 | 说明 | 常见手段 |
|---|---|---|
| 环境 | 与生产环境一致或可模拟 | 容器化、配置管理、混沌工程 |
| 流量 | 可调节请求量、并发数 | 压测工具、流量复制 |
| 数据 | 可构造特定数据集 | 脱敏数据、边界值构造 |
| 状态 | 可重置到初始状态 | 快照、数据库回滚 |
避坑指南:我曾经在复现一个死锁问题时,忘了控制数据库连接池大小。结果复现了 10 次,只有 3 次出现死锁。后来把连接池固定到和线上一样,才稳定复现。控制不到位,复现率就不可信。
3. 可重复(Repeatable)
一次复现可能是巧合。两次复现可能是运气。三次以上,你才敢说「我找到规律了」。
可重复意味着:你写下一份清晰的复现步骤,交给另一个人,他照着做,也能看到同样的故障。
我见过最糟糕的复现文档长什么样?「先跑一下,等一会儿,可能就崩了。」——这哪是复现步骤,这是许愿。
好的复现步骤应该是:
- 准备环境:操作系统版本、依赖库版本、配置参数
- 准备数据:数据库初始化脚本、测试数据文件
- 执行操作:具体的命令、请求参数、操作顺序
- 验证结果:预期现象、日志关键字、监控指标阈值
一个简单的检查标准:如果你的复现步骤里出现了「可能」「大概」「有时候」这些词,说明它还不够可重复。
三大原则的关系
这三个原则不是孤立的。它们像三条腿的凳子,缺一条就站不稳。
- 可观测让你知道「发生了什么」
- 可控制让你知道「怎么让它发生」
- 可重复让你知道「它一定会发生」
只有三者都满足,你才能从「偶然遇到」变成「主动掌控」。
一个真实的复现案例
讲个我亲身经历的事。有一次线上支付服务间歇性返回 500 错误,频率不高,大概每小时出现几次。团队查了两天没头绪。
我接手后,先做了三件事:
- 加观测——在支付接口的入口和出口都打了详细日志,记录请求参数、耗时、异常栈
- 控环境——从线上拉了一台机器,复制了同样的流量比例和数据库状态
- 找规律——用流量复制工具把线上请求回放,同时观察日志
结果发现:每次 500 错误都发生在用户余额刚好等于商品价格的时候。代码里有个 if (balance > price) 的判断,等于的情况走了 else 分支,而 else 分支里有个空指针。
你看,如果没有可观测的日志,我找不到规律;如果没有可控制的环境,我无法隔离变量;如果没有可重复的流量回放,我可能永远等不到那个「刚好相等」的请求。
我的建议:每次接到故障,先花 10 分钟想清楚——「这个故障我能复现吗?如果能,怎么复现?如果不能,缺什么?」想清楚了再动手,比直接冲进代码里翻要快得多。
小结
故障复现不是浪费时间,恰恰相反,它是节省时间的最好方式。三大原则——可观测、可控制、可重复——就是你的检查清单。每次复现前,拿它过一遍,能帮你少走至少一半的弯路。
记住一句话:能复现的故障,已经解决了一半。