通过隧道复制文件时会停顿约一秒,然后继续,而 VPN 日志什么也没记录。应用怪网络,网络怪应用,而交换机端口已经连续运行十一个月。这篇排查从这次停顿入手,向外追到物理链路:端口实际在做什么、对端在做什么,以及你观察期间计数器发生了什么变化。在任何人动手改双工设置之前,这些都值得先做一遍。

从停顿入手,而不是从端口入手

用可验证的方式描述症状。大流量传输中约一秒的停顿,与连接被重置是不同的问题;每小时一次的停顿也与每隔几秒一次的停顿不同。记下负载、方向和大致的间隔。

然后在盯着接口的同时复现它。物理问题会表现为在受影响负载期间计数器发生变化,而 计数器毫无变化 的问题大概率出在链路层之上。要观察一分钟,而不是一秒,因为这类故障往往需要持续流量才会显现。空闲时的监控对一条只在负载下出问题的链路毫无证明力。

这一点很关键,因为双工不匹配有它的特征:错误只在负载下出现,且只发生在流量方向上,而小 ping 和交互式会话却完全正常。如果空闲流量也失败,那就先去别处找原因。

在两端读取运行模式

保存的配置不等于运行状态。端口可能配置为自动协商,最终却落在半双工;也可能配置成对端从未同意的固定速率。要看链路此刻在两侧究竟在做什么。

ethtool eth0
ethtool -S eth0 | grep -iE 'error|drop|collision|fcs'
ip -s link show eth0

记下速率、双工以及自动协商是否开启,然后从相邻交换机或运营商端口取回同样三项事实。只看一端什么也说明不了,因为不匹配是一种关系而不是一项设置。把两行记录并排写进工单,并注明读取时间。这项工作一半的价值就在于把两次读数放在同一处。

如果读不到对端,就无法诊断这个问题。向负责人索取运行模式和计数器,或者在动手改自己这一侧之前先把访问权限安排好。

10/100 半双工的情形是什么样

在 10/100 铜缆链路上,自动协商的一端可以探测到被强制设置的对端速率,却学不到它的双工设置。并行检测从信号判断速率,双工则是被假定而非协商出来的,因此一侧可能停在半双工,另一侧却以全双工运行。

Cisco 的自动协商指南解释的正是这种情形。它不是主张到处关闭协商,也没有对千兆铜缆说出什么有用的东西——在千兆铜缆上双工是固定的,而且必须靠自动协商链路才能起来。

可观察到的证据是只朝一个方向存在的错误组合:全双工一侧的 FCS 或 CRC 错误,半双工一侧的冲突或晚冲突,以及负载下崩塌的吞吐量,而空闲时延迟仍然正常。这种不对称就是特征。仅仅是超卖的链路会在两个方向上、在所有时间都变差。

两端一起改,并留好回退路径

纠正双工是协同变更,而不是局部操作。在对端不同意的情况下强推自己这一侧,正是把一条能用的链路变成坏链路的方式;CLI 接受命令只能证明语法有效。

sudo ethtool -s eth0 speed 100 duplex full autoneg off
ethtool eth0

在跑这类操作之前,先确认平台支持这种组合,并确认对端会在同一时间窗口内一起改。要保留一条独立的管理通道,因为你即将改动的端口,可能正是承载你管理会话的那一个。

在很多现代链路上,正确的做法是让两端都保持自动协商开启,而不是去强制什么。强制是针对特定技术下特定不匹配的补救手段,不是普适的改进。尤其是千兆铜缆,必须依靠自动协商才能把链路拉起来,所以 10/100 的建议并不适用于它。

确认计数器朝好的方向变化

改动之后,重新读取两端的运行状态,确认它们一致。然后用产生停顿的同一负载再跑一遍,并且 比较计数器的增量,而不是累计总量,因为一年累积下来的总量无法告诉你最近十分钟发生了什么。

ethtool -S eth0 | grep -iE 'error|drop|collision|fcs'
ip -s link show eth0
ping -f -c 200 10.90.0.1

在同样负载下不再出现新错误的链路,正是你之前缺少的证据。仍然报错的链路,或者计数器从头到尾根本没动过的链路,会把你推向下一层边界,而不是更深地陷进双工的争论。两种结果都是进展,这已经是配置文件给不了的东西。不要因为第一次读数看起来对,就跳过第二次读数。

把改动前后的数字连同时间戳写进工单。正是这份记录,把「VPN 感觉好多了」变成下一位工程师可以据以推进的东西。

相关文章