安静期过后隧道重新连接,任何日志都没有点名元凶,显而易见的做法是挑那个超时文档最漂亮的设备。这其实是披着诊断外衣的猜测。状态可以在家用路由器、运营商转换器和云边缘存活一段时间,其中任何一处都可能丢弃一条安静下来的流。你能做的替代方案是画出路径,标出哪些设备你真的能观察,再跑一次可以重复的空闲测试。

可重复的测试把传闻变成测量。以下一切都假设只有一个客户端、一个服务器和一种协议,也假设你不会同时改两个变量。目的是让下一次发生比这一次更便宜。

每次都跑同一次空闲测试

写下这条流最后一次已知正常的时间、之后空闲了多久,以及一个新鲜数据包是否把它救了回来。这三项事实才是测量;没有它们,你只有一个笔记本掉线的故事。每次重复都使用同一个客户端、同一个服务器和同一种协议,并记录沉默之后第一个数据包发出的时刻。

然后比较你拥有的每个边界实际看到了什么。决定调查方向的区别在于:暂停之后服务器什么都没收到,还是收到了请求、把回应发进了不再承载回包的路径。

What you observeWhat it suggestsWhat it does not prove
server records no packet after the pausestate was lost upstream of the serverwhich hop dropped it
server answers, client never receivesreturn-path state or filteringthat the timer belongs to the client
client sends nothing at allclient-side timer or application behaviourthat the network path is healthy

不改变五件事来比较路径

第二条获批的接入网络是合理的对照,因为 NAT 链路不同。它同时在运营商、无线条件和可能的地址族上不同,所以结果是边界而不是归因。报告时把限制条件一并记下,不要悄悄丢掉。顺手把路径写下来:设备、角色,以及它的状态到底能不能读。

比较路径买到的是一个被约束过的问题:这条流在一条路径上活下来、在另一条上经历相似沉默后死掉,那么变量就在两者不同的那些环节里。这是真实的结论,即使没有点名任何设备,也告诉下一位工程师该把下午花在哪里、不该花在哪里。

在猜测运营商之前,值得先读本地状态。在 Linux 网关上,conntrack -L 会列出被跟踪的流及其剩余寿命,把关于定时器的猜测变成一个你能看着它到期的数字。要在空闲期之前和之后都读,而不只是之后。

保活能守住什么,守不住什么

受支持的保活能让映射保持打开,而映射保持打开并不能证明它背后的服务还活着。隧道可以仍是映射状态,而它所承载的应用已经停止应答,从状态灯上看这两种情形一模一样。把保活当作对抗空闲过期的保险,而不是健康检查。

把间隔设在真正测到的最短超时之下,而不是论坛上抄来的数字。把保活调到每一种可能定时器之下,是没人需要的流量,而且它也会抹掉那个本该告诉你哪个边界先到期的症状。间隔从测出的数字里取,其余的一概不动。

只改一处,然后再测

在一次实测里,忍住把每个超时都调高、把每个网关都刷一遍的冲动。那会擦掉你想要的证据,还会打断别人的流,对还没验证的假设来说是笔坏买卖。在一个设备上改一个受支持的设置,然后重复空闲期和应用的恢复过程。

记录哪个边界的观察发生了变化,即使什么都没变好也要记。没修好任何东西的设置也是信息,察觉一次比铺开到整个环境更便宜。

写一份你站得住的结论

当上游转换器无法检查时,只说明证据支持的内容:交换在这段路径的某处、经过那么长的安静之后死掉,负责的那一跳仍未归因。有界陈述经得起复核,也能把下一个人指向正确的段落。把隐藏的路由器说成原因则两件事都做不到。把这条有界结论连同间隔一起交给那段不可观测路径的负责人。

RFC 4787 说明了为什么 UDP 映射定时器很难只从一个端点推断,而这种困难正是有界结论才是诚实结论的原因。定时器是真实存在的,围绕它们的不确定性也是。

相关文章