TT Lab
开始
学习 学习路径 课程

调试实战

把能用的和不能用的并排摆出来

在 TT Lab 中继续学习

一句话总结

鉴别诊断不是只盯着失败样本,而是把成功样本并排摆在一起,只保留“存在于所有失败中、且不存在于任何成功中”的属性。

为什么需要它

“有的客户可以,有的客户不行。”这是现场最常听到的一句话,同时也是最好的消息。因为有一部分是正常的,就意味着有可以比较的对照组。

但大多数人放弃了这个消息,只去钻研失败请求的日志。失败日志里有 TLS 握手,有重试,有警告,看起来全都可疑。要知道这些可疑之处是否真的是原因,就必须看成功请求的日志里是否也有同样的东西。如果成功里也有,它就不是原因,而是背景。

这套流程是有名字的。它来自医学,叫鉴别诊断(differential diagnosis),在软件领域中也常称为差异诊断。核心只有一点——只看一边,什么都像原因候选;两边都看,大部分会自行被排除。

工作原理

流程分四步。

1. 收集样本。只收集二十个失败样本没有意义。成功样本也要收集差不多的数量。这时,成功样本越是与失败条件最接近的成功越好。来自完全不同国家、不同版本的成功样本,能排除掉的东西很少。

2. 按属性展开。把每个样本变成“属性 = 值”的列表:地区、客户端版本、编码、认证方式、设备、端点、时间段。确定这个列表,实际上是最难的一步——不在列表中的属性,永远不会成为候选。

3. 做两个集合的减法。从所有失败中都有的值的集合中,减去哪怕只在一个成功中出现过的值的集合。剩下的就是候选。这里被排除的值很重要。“所有失败中都有 token 认证”这个事实,一旦与“成功样本中也有三分之一是 token 认证”这个事实放在一起,就什么也说明不了了。

4. 如果候选有两个以上,就把它们分开。这是这套流程真正的难点。

相关不等于原因。如果在同一时期部署的两件事总是同时出现,仅凭样本无法区分它们。表格对二者指向完全相同,并不是因为表格错了,而是因为数据中没有能把二者分开的案例。分开的方法只有两种。

也有无法用单个属性区分的情况。如果只有在编码为 utf-8-sig 且设备为 kiosk 时才会失败,就一个单独的候选也不会留下。因为各自在成功样本中也存在。这时要把值的配对作为候选,再做一次同样的减法。如果继续去看三个及以上的组合,情形数会迅速增加,所以通常看到配对为止,之后用干预来确认。

从数字上看,这套流程为什么有价值就很清楚了。假设有 240 条样本,七个属性,大约二十种值。求 40 条失败的交集,通常会剩下两三个值,再从中减去 200 条成功的并集,就只剩一两个。用眼睛扫一遍,二十个全都可疑,而两次减法,候选就只剩一两个。并不是人变聪明了,而是成功样本替我们排除了其余的。

还有一点。这套流程属性越多越强。记录中没有的属性不可能成为候选,所以在调查初期决定“要一并记录什么”,实际上占了调查的一半。请求头、客户端版本、租户、路径、认证方式,在大多数事件中都有用。

在现场相遇的样子

第一,只收集失败样本。客户只会把失败的发给你,因为成功的没有人保留。所以第一个请求总应该是“成功的也请发同样数量”。

第二,样本有偏。如果失败全都从夜间批处理中收集,成功全都从白天的界面中收集,时间段和路径就会全部作为候选保留下来。收集数据的方式在数据上留下了规律。

第三,只找到一个候选就停下。候选剩下两个时,挑其中看起来更像的一个去报告,有一半的概率会错。而且这样的报告会让修复白白花掉好几天。候选有两个,就写两个,并设计能把它们分开的实验,这才是对的。

第四,不记录被排除的东西。“auth_mode 不是原因”这个事实,能让下一个人不再走同样的路。报告中不仅要写剩下的候选,还要一并写下被排除的候选和排除的依据。

实际工作中真正重要的事

下一项实验要做什么

用支付网关的 240 条样本制作按属性划分的差异表,挑出存在于所有失败中、且不存在于任何成功中的值。在剩下两个候选的地方,再加入 120 条新样本排除其中一个,并用复现器只改变一个属性,确认结果是否翻转。最后,在另一个无法用单个属性区分的租户样本中找出配对候选,汇总成一页纸进行报告。