技术2026 · 09 / 147 分钟♡ 53评论 11

日志里什么都看不出来的故障,我是怎么查的

两边的日志都显示「正常」,但产物就是出不来。这类故障占了我近两年排查时间的一大半,这篇写我摸出来的三步法。

第 214 次重跑,这次过了

最难查的故障不是报错的那种。报错的故障有堆栈、有错误码、有一句话告诉你哪里不对。

最难查的是这种:上游说「我发了」,下游说「我没收到」,中间的每一个环节都说「我正常」。 日志翻三遍,没有一行是红的,但产物就是没有。

过去两年我在这类故障上花的时间,比所有报错故障加起来还多。下面是我最后摸出来的一套做法,不保证通用,但每次都管用。

第一步:别看日志,先画时间线

日志是按组件分的——A 的日志、B 的日志、C 的日志。而这类故障几乎都发生在组件之间,也就是日志覆盖不到的地方。

所以我第一件事不是翻日志,是把所有组件的关键事件按绝对时间抄到同一张纸上:A 在几点几分几秒发出、B 在几点几分几秒收到、B 几点开始处理、几点回应……

画到一半,问题常常就自己浮出来了。上一次是这样的:A 发出后 4.8 秒收到 B 的确认,但 B 的日志显示自己在 A 发出后 5 秒才开始处理。确认比处理早——那个确认是谁发的? 顺着这条线查下去,是中间一层代理在替 B 应答,然后自己把请求丢了。

单看任何一方的日志,这件事都是「正常」的。

第二步:拿报文原文对照,不要凭印象

第二步最反直觉:不要相信自己对代码的理解,去看实际发出去的东西。

有一次我断定问题出在请求格式上,因为「我记得那里多带了一个端口号」。改了、重试、没用。最后把两边真实的报文原文摆在一起,发现端口号一直都在,打通的那几次也带着——我改掉的是一个从来就没坏的地方,还把它改坏了。

那之后我给自己定了规矩:任何「我觉得是因为 X」,在改动之前先拿原文验证 X 是不是真的。 报文、配置、环境变量、实际调用的路径,全部看原文,不看记忆。

这条规矩省下的时间,比任何调试工具都多。

第三步:做一个只做一件事的探针

如果前两步还没找到,就写探针。

探针的原则是剥掉一切业务逻辑,只保留要验证的那一条链路。比如怀疑是网络层的问题,就写一个二十行的脚本,只发一个最小请求、只看有没有回应,不做任何解析、不带任何重试。

然后做对照组:正确的目标发一次、错误的目标发一次、内部的目标发一次。三个结果放在一起,责任边界一下就清楚了——能拿到明确错误的那一段是健康的,「受理了但没有下文」的那一段才是故障所在。

探针要小到能在几十秒内跑完,否则你会舍不得多跑几次对照。

一个附带的教训

复现故障的时候,不要顺手改任何参数。

有一次为了让输出更好看,我在复现时改了一个无关的选项,结果撞上了一条我不知道的路由规则,把原本要验证的那条链路整个换掉了。我对着一个根本不是原故障的现象查了半天。

复现就是复现,要逐字复刻已知出问题那一次的配置。想优化,等查完再说。


写下来之后发现,这三步没有一步是「技术」。画时间线、看原文、做对照,全是很朴素的方法。

难的从来不是方法,是在焦虑的时候还愿意先慢下来做这三件事。

这篇里的照片Frames全部相册 →
十年的工具,换过的没剩几件
十年的工具,换过的没剩几件家 · 书桌 · Sony A7C II · 50mm f/5.6
← 更早一篇
显存不够的时候,我先砍的不是模型

关注公众号「十年追随」

新文章第一时间推给你。留言我都会回,公众号里也能收到回复通知。 不发广告,一周最多两条。

十年追随 公众号二维码
评论Comments11 条 · 匿名也能评,昵称头像会记住
评论服务(Waline)待部署 —— 香港 VPS 起来后填 SERVICES.waline 即生效。
想说话可以先去 留言板,那边我每条都回。
关注公众号「十年追随」更新第一时间推给你 · 留言也能收到我的回复
看二维码