"ping 正常,但业务偶发 telnet 不通,概率大概是 0.07%。"
当业务方抛出这句话时,任何有经验的网络工程师都会心头一紧。
在生产环境中,最怕的不是 100% 的宕机——那反而简单,重启、切换、回滚,三板斧下去总能止血。
真正让人头皮发麻的,是这种时隐时现的"幽灵丢包"——它不会触发告警,却能让用户的页面偶尔转圈两秒。
你知道它在那里,却抓不住它。
▲ 业务方丢出的原始监控截图 — 0.07% 的概率性超时
⏰ 故事从某天晚上 22:42 开始 ⏰
一、案发现场:看似风平浪静,实则暗流涌动
业务方告诉我们什么?
那天晚上,业务同学在群里贴了一张监控截图。我们花了几分钟把它翻译成网络语言:
📌 业务语言:多台业务机器访问某数据中心的多个 LB VIP,偶发超时。
📌 网络语言:ping(三层)测试完全正常,但 telnet/TCP(四层)存在约 0.07% 的超时——时高时低,有时 0.1%,有时 0.03%。
📌 时间线:异常从当晚 22:42 开始出现。
交叉验证,拼凑拼图
线索到手,接下来该干什么?交叉验证,控制变量。这是排查网络问题的第一板斧:别急着下结论,先摸清楚这个问题到底"传染"了多大范围。是某台机器的个体问题,还是一整片区域在生病?
我们排出了两位"探针"和四个"目标":
角色 |
身份 |
地址 |
类型 |
客户端 A |
业务反馈的"案发现场"机器 |
|
云上机器 |
客户端 B |
我们自己的"探针"机器 |
|
物理机器 |
服务端 X |
LB VIP |
|
LB VIP(20 个 RS) |
服务端 XRS |
X 背后的真实 RS |
|
VIP 后端 RS(ECS) |
服务端 Y |
另一个 LB VIP |
|
LB VIP(20 个 RS) |
服务端 YRS |
Y 背后的真实 RS |
|
VIP 后端 RS(ECS) |
然后让两位客户端挨个去"敲门"——我们抱着一丝侥幸:也许只是客户端 A 自身的问题?
服务端 X |
服务端 XRS |
服务端 Y |
服务端 YRS |
|
客户端 A |
❌ 概率超时 |
✅ 正常 |
❌ 概率超时 |
❌ 概率超时 |
客户端 B |
❌ 概率超时 |
❌ 概率超时 |
❌ 概率超时 |
❌ 概率超时 |
▲ 交叉验证:两个客户端 × 四个目标的全排列连通性测试
结果出来的那一刻,我们意识到问题没那么简单——无一幸免。不管是云上还是物理机器,不管敲的是哪个 VIP 的门,全部概率性超时。这不是某台机器的"个体问题",而是一整批 LB VIP 的"集体症状"。
顺着这条线一查,果然:这些 VIP 全部归属同一个 LB 集群。
🧩 第一块拼图问题锁定在某个 LB 集群。
更有意思的是接下来的对比:绕过 VIP,直接去敲后端 RS 的门呢?
- 物理机器直连 RS,万次请求里偶尔冒出几个超时;
- 云上机器直连 RS,万次请求,纹丝不动,一个超时都没有。
这个对比结果很微妙。后端 RS 本身大概率没问题——起码云上机器访问它毫无障碍。问题更可能出在物理机器 → 后端 RS 这一段链路上。两者的关键差异:物理机器跨网络域转发跳数更多,云上机器走内部转发路径更短。记住这个差异——它后面会成为解开谜题的关键钥匙。
二、第一轮排查:VIP 健康检查暴露关键线索
VIP 监控大盘 & 健康检查日志
▲ 24 小时 LB 健康检查失败时序分布 — 细微但有节奏感的毛刺
既然嫌疑指向同一个 LB 集群,先看 VIP 监控大盘。果然,大盘上偶发有异常跳动——不是惊天动地的尖峰,而是一种细微的、有节奏感的毛刺,像心电图上偶尔多出来的小波。
更关键的线索藏在健康检查日志里。LB VIP 到后端 RS 的四层健康检查频繁超时,而且失败的 10 台 RS 全部属于同一个 /24 网段:
▲ 健康检查日志:失败的 10 台 RS 全部来自同一个 /24 网段,非随机故障
十台机器散布在同一个 /24 网段,全部间歇性健康检查失败。这不像是随机服务故障——RS 本身的问题不可能十台同时生同一种病。更像是它们脚下的"路"出了问题。LB 本身也是物理服务器,与刚才"问题可能出在物理机 → 后端 RS 链路"的推断一致——很可能是相同的一段物理链路在作妖。
先确认三层
▲ 网络排查铁律:自底向上,逐层确认
排查网络问题有个基本原则,像建筑工人查漏一样:从下往上,三层 → 四层 → 七层,逐层确认。
- 多个客户端 ping 各 VIP 及后端 RS,一致结果:全部正常,无丢包。
- traceroute 路径也正常,九跳全部响应,无高延迟。
三层很干净,嫌疑聚焦四层——和预期一致。
抓包:大海捞针的困境
▲ 万分之一超时率的抓包犹如大海捞针,pcap 文件膨胀到几百兆
既然打流机能复现万分之几的超时,那就抓包看看吧。打流机对后端 RS 持续打流,tcpdump 全量抓包。一分钟,pcap 膨胀到几百兆。
打开 Wireshark,密密麻麻的报文像瀑布一样涌过来。
几万个连接里,只有万分之一的那几个异常——混在正常连接的汪洋大海中,不会主动举手说"我是坏的"。
时间一分一秒过去,报文列表越滚越长,耐心越磨越薄。
这条路真的行得通吗?我们开始怀疑,也许该换个方向了。
至此,VIP 健康检查、三层验证、抓包分析都指向同一个方向——问题在中间链路,但具体在哪?我们还不知道。
三、抽丝剥茧:从"概率玄学"到"科学实证"
面对 0.07% 这种"薛定谔式"的故障,盲目重试毫无意义。如果不能稳定复现,所有分析都像在沙子上盖房子。我们需要一个突破口——把随机变成确定。
第一步:打破概率幻觉,从 0.07% 到 100%
转机出现在我准备放弃抓包分析的时候。换了一个思路:与其大海捞针地找异常包,不如反过来想——这些异常包有没有什么共同特征?
重新审视那些零星的超时连接,逐个比对五元组信息。看了十几条之后,一个隐约的规律浮了出来:
🔑 丢包不是随机的,而是与源端口强绑定。
验证方法很简单——curl 有一个参数 --local-port,可以指定源端口:
▲ 异常端口 55559 = 100% 超时,正常端口 35559 = 瞬间返回
反复验证后发现:只要指定特定源端口(如 55559),curl 请求就会100% 稳定超时;换一个端口(如 35559),秒级响应,从不失手。
▲ 从 0.07% 概率到 100% 确定性 — 整个排查的转折点
💡 转折点就像你在漆黑的房间里摸了半天墙壁,指尖忽然碰到了电灯开关。"咔嗒"一声,整个房间亮了。
整个问题从"每次试上万次才能碰到一次",变成了"每次都能稳定复现"。一旦能 100% 复现,剩下的就只是时间问题了。
🔬 技术洞察端口级确定性丢包,通常指向底层设备的 ECMP 哈希桶异常、TCAM 表项冲突或特定流表损坏。当丢包行为能精确到特定源端口时,意味着问题出在流量转发路径的确定性选择环节。
第二步:逐跳追踪——报文消失在哪一跳?
先缩放到全局视角,看这段跨域访问的完整转发路径。从客户端 B 发出 TCP 请求到后端 RS 收到,中间经过了十余个网络节点:
▲ 跨域访问完整转发路径:IDC-A → IDC-B → IDC-C
完整转发路径(逐跳拆解)
源端 · IDC-A 机房
NC → 接入交换机 → 汇聚交换机 → 核心交换机 → 核心路由器 → 边界路由器 → 骨干路由器
跨域骨干 · IDC-B 中转
骨干路由器 (IDC-B) → 骨干路由器 (IDC-B)
目的端 · IDC-C 机房
骨干路由器 → 核心路由器 → 接入交换机 → 云网关 → VXLAN 隧道 → NC(宿主机 / RS)
第 9 跳接入交换机到目的端 NC 之间,报文以 VXLAN 封装在隧道中传输。中间所有物理设备看到的都是外层封装报文,而非原始业务报文。
📚 ECMP 等价多路径路由网络中有多条等价路径时,交换机根据五元组(源 IP、目的 IP、源端口、目的端口、协议)做 hash 决定走哪条路。不同源端口,可能被 hash 到完全不同的物理路径。
"特定源端口丢包"的物理解释就此成立:某条 ECMP 路径上的设备出了问题。
源目的抓包对比
有了稳定复现手段,可以精准对比实验了。VXLAN 封装报文有"内外两层"——内层是原始 TCP 报文,外层是 VXLAN 隧道头。我们在确定源端和目的端的 NC 上分别抓包:
源端发出 |
目的端收到 |
|
正常端口 35559 |
✅ SYN 发出 |
✅ SYN 收到 |
异常端口 55559 |
✅ SYN 发出 |
❌ 什么都没收到 |
报文确确实实从源端发出去了。但目的端仿佛聋了——中间那条 VXLAN 隧道像被截断的管道,报文进去了,再也没出来。
TRACEROUTE 对比:两条路,两个命运
报文"蒸发"在哪一跳?traceroute 的 --sport 参数可以指定源端口:
跳 |
正常端口 35559 |
异常端口 55559 |
H5 |
IDC-A 边界路由器 |
IDC-A 边界路由器 |
H6 |
IDC-A 骨干路由器 |
IDC-A 骨干路由器 |
H7 |
IDC-B 骨干路由器 |
IDC-B 骨干路由器 |
H8 |
IDC-C 核心路由器-1 ✅ |
IDC-C 核心路由器-2 ⚠ |
H9 |
IDC-C 接入交换机 ✅ |
* * *(无响应)❌ |
两条路径从第 5 跳分叉:正常流量走 核心路由器-1,一路绿灯;异常流量走 核心路由器-2——到了这里就断了,第 9 跳变成三个冰冷星号。
就像两个快递员从同一个仓库出发,在岔路口被分到不同车道。走路由器-1 的,一路绿灯到目的地;走路由器-2 的,开进去就再也没出来。
接入交换机往后的设备看不到?因为 VXLAN 封装后,后续设备只转发外层包头。接入交换机是我们能做有效匹配的最后一跳——排查重点就是 核心路由器-2 往后的链路。
"0.07% 概率不通"的本质:绝大多数源端口 hash 到正常设备,少数刚好 hash 到有问题的核心路由器-2。不是概率在作怪,是 hash 函数忠实地把特定流量送进了同一个黑洞。
第三步:全网流统排查,揪出黑洞节点
高度怀疑核心路由器-2,但需要铁证。拉上网络团队,对关键设备逐跳进行流统排查。
▲ 从目的端一路回推,逐跳比对流统结果
从目的端一路往回排查:
抓包 / 流统节点 |
正常端口(35559) |
异常端口(55559) |
目的宿主机(AVS) |
✅ 收到 |
❌ 收不到 |
云网关 |
✅ 收到 |
❌ 收不到 |
接入交换机 |
✅ 收到 |
❌ 收不到 |
核心路由器-2 |
✅ 进 & 出 |
⚠ 只进不出 |
🎯 锁定目标:IDC-C 核心路由器-2。异常流量到达后,如同掉入黑洞,有进无出。
四、真相大白:硬件设备的"隐秘角落"
经基础网络同学确认:核心路由器-2 存在底层转发异常。
特定哈希桶对应的硬件表项状态异常,导致匹配该特征流的报文被——🔇 静默丢弃
不报错、不告警、不留痕迹。只是安静地把报文吞掉了。
处置方案:立即将该异常节点从转发平面隔离——相当于把高速公路上那条塌陷车道封掉,所有流量自动走其他正常车道。
▲ 隔离瞬间,毛刺消失,打流恢复正常
隔离的瞬间,打流测试立刻恢复正常。0.07% 的超时,消失得无影无踪——就像它从来没有存在过。
最后一块拼图:变更时间线
找到故障设备、隔离、恢复——到这里大部分人觉得故事结束了。但有一个问题一直在我脑子里转:为什么偏偏是那个时间点?
这台核心路由器-2 如果一直有问题,怎么之前没人报过?如果是最近才坏的,有什么变更触发了它?
▲ 变更时间线:22:20 → 22:37 → 22:42,三条关键时间点完美吻合
就在准备隔离设备的同时,我翻出了一条关键信息:
"172.16.20.0 网段当天 22:20 开始从区域 A 接入交换机切到区域 B。引流操作完成约22:37。"
业务异常起始时间——22:42。时间线完美吻合。
核心路由器-2 的 VOQ 映射缺陷可能早就潜伏了——几天、几周、甚至几个月。它一直安安静静,因为之前没流量走这条路径。
💣 它是一个沉睡的地雷。这次网段迁移变更改变了流量走向,把原本不经过它的流量引了上来。地雷被踩响了。
🤔 为什么变更信息发现这么晚?
网段级引流操作对上层完全透明,由网络运维团队底层执行。变更藏在一个很难关联到的信息孤岛里——直到故障范围精确到特定设备和网段,才有足够线索反向追溯。
根因追踪:VOQ 映射异常
但故事没有到此结束。隔离设备只是"止血",不是"治病"。我们还不知道这台设备到底哪里坏了,也不知道同型号其他设备会不会有同样问题。设备厂商介入后地毯式排查底层转发表项,最终锁定了一个极其隐蔽的 Bug:VOQ(Virtual Output Queue,虚拟输出队列)映射异常。
▲ VOQ 映射异常:错误映射表项指向不存在的出口队列
VOQ 是什么?打个比方
想象一个巨大的快递分拣中心,每个出口城市都有专属分拣通道——上海走 A 通道,北京走 B 通道。这就是 VOQ 的核心:为每个出端口维护独立队列,即使上海传送带堵了,北京的包裹也不受影响("避免队头阻塞")。
但现在出了个问题:其中一条传送带的标签贴错了。本该通往上海的 A 号传送带,被错误映射到一个不存在的出口。所有分配到 A 号传送带的包裹,就这样无声无息掉进了传送带尽头的黑暗里——没有到达,也没有退回。
更要命的是,这个分拣中心没有"退件通知"机制。包裹丢了,寄件人和收件人都不知道。没有告警,没有日志——除非有人拿着快递单号,从头到尾追踪每一个中转站,才能发现包裹在哪个环节消失。
这正是核心路由器-2 上的情况。特定流量模型下 VOQ 映射表项错乱,大部分流量走正常通道,少数源端口流量刚好 hash 到错误映射槽位——这就是"0.07% 概率性不通"的终极根因。
最终,板卡重启修复了映射表项,设备回滚入网,一切恢复正常。
五、排查路径总览
回头看这场排查,每一步都在缩小包围圈,逼近真相:
▲ 六阶段排查全景:
信息收集 → 100% 复现 → traceroute → 流统 → 隔离 → 根因闭环
1. 信息收集与交叉验证
排列组合锁定某 LB 集群;分层测试排除三层,嫌疑聚焦四层;RS 验证证明后端服务无辜,问题在中间路径。
2. 突破——源端口规律
从抓包万分之一噪声中发现源端口规律,固定端口实现 100% 复现。这是整个排查的转折点。
3. traceroute 对比
揭示 ECMP 分叉的两条命运迥异的路径。
4. 全网流统
逐跳排查,确认核心路由器-2 "只进不出"的铁证。
5. 隔离恢复 & 根因闭环
隔离故障设备,业务瞬间恢复;厂商追踪到 VOQ 映射异常,板卡重启修复,闭环收官。
六、避坑指南 & 技术沉淀
本次排查虽是小概率事件,但沉淀的方法论极具复用价值:
🚨 警惕"平均数陷阱"
0.07% 是全局统计值,掩盖了局部 100% 的致命缺陷。排查第一步,永远是寻找确定性复现条件——固定源端口、固定目的 IP、固定协议——把概率变成确定。
🔍 概率性问题一定有规律
网络中的"概率性"故障,底层几乎不会是真正的随机。它只是被 ECMP hash、负载均衡、连接复用等机制"打散"了。找到那个区分变量并固定它,概率就变成了确定。
丢包与特定端口强相关时,优先怀疑:ECMP 哈希碰撞、ACL 策略误匹配、TCAM/FIB 表项损坏或溢出、网卡 RSS 队列异常。
⏱ 变更关联:永远先看时间线
"异常开始时间点前后有没有变更?"——这个问题应始终放在排查清单前几项。真相往往不是藏在数据包里,而是藏在变更记录里。
🩸 设备级根因要追到底
隔离设备只是"止血",不是"治病"。厂商追踪到 VOQ 映射异常,确认软件 Bug,板卡重启修复。没有这一步,我们只知道"这台设备有问题",却不知道为什么、会不会再次发生。根因分析是闭环的关键——不追到底,幽灵还会回来。
结语
那个 0.07% 的幽灵,最终被钉在了一块路由器板卡的 VOQ 映射表里。
它不是什么神秘力量,只是一个尚未被观测到的 Bug——潜伏在硬件深处,等待一次变更把流量引到它面前。
从 0.07% 的模糊反馈,到 100% 的端口级复现;从业务层的抖动告警,到物理层核心路由器的"只进不出"——每一次精准定位的背后,都是对网络协议栈的敬畏与对排查方法论的坚持。
所有的"玄学",都只是还没找到那个确定性的源端口。
技术人的浪漫,
就是把「偶尔不通」
变成「永远稳定」。
本文基于实际排查案例整理,IP 地址、设备名称、机房编号等均已脱敏处理。全链路协作:业务团队负责业务侧测试与分析,网络团队负责设备侧流统与隔离。跨域问题,就得跨团队来解。
💬
你在生产环境中遇到过
最诡异的网络问题是什么?
是怎么定位到的?
👇 评论区等你分享排查故事
来源 | 阿里云开发者公众号
作者 | 徐旭、康鑫磊