一次跨国丢包排查实录:从 ping 完美到 tcping 全军覆没的 4 小时

2 阅读6分钟

凌晨 3:47,客户群里第三次 @ 我。这次的故障,用 ping 完全看不出来。

起点:一封"网络很慢"的工单

故事开始于一个再普通不过的周三凌晨。

我们有一个部署在新加坡的服务,给国内客户提供 API 调用。当晚客服小姐姐转过来一个 P1 工单,描述很简单:

"调用超时,但是我能 ping 通你们的服务器,延迟也才 80ms。这是不是你们的问题?"

按照我们的常规剧本,遇到这种情况第一反应是甩锅——ping 通且延迟正常,那大概率是客户那边代码或本地网络的问题。但工单里截图来了:

$ ping api.example.com
PING api.example.com (xxx.xxx.xxx.xxx): 56 data bytes
64 bytes from xxx.xxx.xxx.xxx: icmp_seq=0 ttl=49 time=72.341 ms
64 bytes from xxx.xxx.xxx.xxx: icmp_seq=1 ttl=49 time=71.892 ms
64 bytes from xxx.xxx.xxx.xxx: icmp_seq=2 ttl=49 time=72.105 ms
64 bytes from xxx.xxx.xxx.xxx: icmp_seq=3 ttl=49 time=71.998 ms
--- api.example.com ping statistics ---
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 71.892/72.084/72.341/0.166 ms

漂亮的 ping 结果。0% 丢包,72ms 延迟稳定到小数点后第二位。这看起来比我家公司内网都健康。

但客户随后又发了一张图——他们的应用日志里,过去 30 分钟有 60% 的请求 connection timed out

这两个信息凑在一起,整个事情就开始变得有意思了。

第一刀:ping 看到的 ≠ 业务看到的

很多人下意识把"ping 通"等同于"网络正常",这是排查里最常见也最致命的误区。

ping 用的是 ICMP 协议,本质上只是发个回声请求看对端 IP 是否存活。它不走 TCP,不经过应用层端口,更不会触碰你的负载均衡、防火墙策略、连接数限制。换句话说:

测试维度ping 能验证ping 不能验证
IP 是否可达
端到端延迟✅(ICMP 路径)
目标端口是否开放
防火墙是否拒绝 TCP
服务进程是否健康
TLS / HTTP 是否正常

很多企业的边界设备甚至会优先放行 ICMP(避免被监控误报"机器掉线"),但同时对 TCP 流量做严格限制。在这种网络下,ping 永远漂亮,业务永远报错。

所以收到截图的第一秒,我就知道这次甩不了锅。

第二刀:换 tcping,真相浮出水面

让客户在他那边对我们的 443 端口做 tcping:

$ tcping api.example.com 443
Probing xxx.xxx.xxx.xxx:443/tcp - No data : seq=0 (failed)
Probing xxx.xxx.xxx.xxx:443/tcp - No data : seq=1 (failed)
Probing xxx.xxx.xxx.xxx:443/tcp - Port is open - time=158.421ms
Probing xxx.xxx.xxx.xxx:443/tcp - No data : seq=3 (failed)
Probing xxx.xxx.xxx.xxx:443/tcp - No data : seq=4 (failed)
Probing xxx.xxx.xxx.xxx:443/tcp - Port is open - time=312.998ms
Probing xxx.xxx.xxx.xxx:443/tcp - No data : seq=6 (failed)

来了。TCP 层 70% 失败,偶尔成功的也延迟翻倍——同一时刻 ICMP 层却 0% 丢包。

到这里基本能下一个判断:丢包不是发生在我们机房的接入层,也不是客户端本地——一定是中间某一跳路由器对 TCP 流量做了选择性丢弃,但对 ICMP 放行。

很多 ISP 的跨境节点在拥塞时会优先丢 TCP(特别是大包),ICMP 包小且不携带载荷,反而能"幸存"。这就是为什么 ping 漂亮但 tcping 全军覆没。

⚡️ 顺手记一个反直觉的事实:你 tcping 看到的延迟可能比 ping 高一截。原因是 ICMP 是单包来回,而 TCP 三次握手要经过排队、重传可能性更大,且部分网络设备给 TCP 的处理优先级低于 ICMP。所以同一目标,tcping > ping 是常态,反过来才奇怪。

第三刀:mtr 定位到具体哪一跳坏了

知道是中间路由的问题不算结案,得找出具体是哪一跳。这时候 traceroute / mtr 上场。

mtrtraceroute 强的地方在于它持续发包统计每一跳的丢包率,而不是只跑一次:

                                  Packets               Pings
 Host                            Loss%   Snt   Last   Avg  Best  Wrst StDev
 1. 192.168.1.1                   0.0%   100    0.4   0.5   0.3   1.2   0.1
 2. 10.32.0.1                     0.0%   100    3.2   3.4   2.9   8.1   0.6
 3. 218.xx.xx.1                   0.0%   100    8.7   9.1   8.2  15.4   1.0
 4. 202.xx.xx.85                  0.0%   100   12.3  12.8  11.9  18.6   0.8
 5. 219.xx.xx.149                 0.0%   100   45.2  46.1  44.8  52.1   1.2
 6. 202.xx.xx.34                 67.0%   100   71.5  78.2  68.9 145.3  18.4   ← 这里
 7. 203.xx.xx.18                 65.0%   100   72.8  79.1  69.2 152.7  19.1
 8. 103.xx.xx.142                65.0%   100   73.2  80.0  70.1 158.4  20.2
 9. xxx.xxx.xxx.xxx              66.0%   100   72.6  79.5  69.8 155.2  19.6

第 6 跳开始出现 65%+ 的丢包,且后续每一跳的丢包率都跟着传播——这是教科书式的单点拥塞

⚡️ 看 mtr 输出的小窍门:只有第一跳出现高丢包而后续跳没有传染,往往是那一跳路由器对 ICMP 限速(不是真丢),可以忽略。从某一跳开始所有后续都丢,那才是真问题。

第四刀:从一个节点测,永远只是一面之词

这一步是我那晚最大的认知刷新。

我让客户从他自己机器跑出来上面的 mtr 之后,本来想直接拿这个证据去找上游 ISP。但我们 SRE Leader 拍我一下:"你确定这是公网问题,不是客户那条出口的问题?"

是啊。单点测试有个根本缺陷:你看到的拥塞,可能只属于你这条 ISP 路径。 同一时刻从不同地区、不同运营商访问,可能完全没事。

所以我让客户的同事在另外几个城市的机器上同步跑 tcping 和 mtr。结果是:

  • 北京电信 → 新加坡:丢包严重,定位到香港某中转节点
  • 北京联通 → 新加坡:完全正常
  • 上海移动 → 新加坡:丢包,但定位到不同的中转节点
  • 广州电信 → 新加坡:完全正常

到这一步证据链就完整了:问题确实在公网,且是电信跨境出口拥塞。但只看客户那一台机器,根本不可能得出这个结论。

那晚我手动协调了 4 台机器在不同地区同步跑测试,光是同步操作就花了快 2 小时。后来我意识到这种"多节点同步对比"其实就是典型的网络诊断刚需,市面上有不少现成的多节点测试平台可以一键搞定,比手动开 4 个 SSH 高效太多。我现在团队里这种活基本都丢给在线工具跑——拿个图就走,比手动方便一万倍。

复盘:可复用的 4 步排查方法论

凌晨 5 点多事情解决(ISP 给我们换了一条 BGP 路径),那晚熬出来的方法论我后来整理成一个 SOP,团队新人遇到类似问题照着跑就行:

第 1 步 · ping 验存活,但不下结论 ping 通只代表 IP 存活,不代表服务可用。无论 ping 结果多漂亮,绝对不要跳过下一步。

第 2 步 · tcping 验业务端口 直接打你的业务端口(80 / 443 / 3306 / 自定义端口),如果 tcping 失败而 ping 成功,几乎可以锁定中间路由对 TCP 流量异常。这一步是排查的核心节点。

第 3 步 · mtr 定位异常跳 持续发包至少 100 次(mtr 默认 10 次太少容易误判)。看从哪一跳开始连续丢包,那就是事故现场。

第 4 步 · 多节点对比定锅 单点测试只能描述现象,不能定位根因。同时在 3 个以上不同地区/运营商的节点跑测试,对比结果,才能区分是"公网问题""客户出口问题""目标机房问题"还是"特定 ISP 跨境路径问题"。

一些后续的思考

这次事故让我系统性地把网络诊断工具梳理了一遍,几个心得分享:

ICMP 不等于业务,永远以业务协议(TCP / HTTP)为准做最终判断。监控告警里如果只挂了 ping 探测,是非常脆弱的。

单点视角是排查的最大陷阱。最少要从 3 个不同 ASN 的节点对比看,不然永远在猜。多节点测试这事手动做太累,建议直接用现成工具,比如我现在常用的 BiuPing,全国节点 + 多运营商 + IPv4/IPv6 双栈都打通了,ping、tcping、mtr、网站测速一个站搞定,跨国排查特别顺手。

给监控加上 tcping 探针。光监控 ping 在 90% 的故障里都会失效——你的服务挂了,但你的 ICMP 还在欢快地回应。这种监控不如不要。

保存历史基线。同一个目标在正常时候的 mtr 路径长什么样、每一跳延迟大概多少,平时多看几眼,出问题时一眼就能看出"这条路径不对劲"。


工具是死的,方法论是活的。下次再遇到"ping 得通但访问不了"的工单,别下意识甩锅,先按这四步走一遍——大概率你会比客户更早发现真凶。