2901 字
15 分钟

中间跳丢包 90% 需要管吗:一次 traceroute 误读的完整拆解

给博客跑路由追踪,中间好几跳丢包率 87%~99%,看着像骨干网炸了,站点却照样能开。本文用 tcptest.cn 的多节点数据和本机实测,讲清 ICMP 限速、控制平面与转发平面的区别,并给出一张"什么时候该管"的判据表。
10月5日 22:05
网络排障测量

上一篇给博客做全国 Ping 体检测出:Cloudflare 免费套餐在国内访问平均 233ms。这次我想知道得更细一点——这 200 多毫秒,到底花在路径上的哪些路由器了?

于是我在 tcptest.cn 上跑了一次从福建泉州电信到 blog.juluo.work 的在线路由追踪。结果第一眼挺吓人:中间连续几跳的丢包率是 99%、87%、97%。

只看这三个数字,结论应该是”电信骨干网崩了”。可博客当时打开得好好的,多节点 Tcping 也显示 443 端口正常(数据见上一篇)。

提示

本文数据均为 2026-10-05 晚实测:多节点数据来自 tcptest.cn 的在线路由追踪(福建泉州电信节点,每跳 100 个探测包);本机数据来自 Windows 上的 tracert、ping 和一段 TCP 连接测试脚本。所有截图都来自真实执行结果。

那张追踪表到底显示了什么#

tcptest.cn 在线路由追踪结果:福建泉州电信到 blog.juluo.work,第 11 至 14 跳显示 87%~99% 丢包,末跳只有 10%

把关键几跳摘出来(丢包率一列是按 100 个探测包统计的):

跳IP归属丢包率平均延迟
1117.24.4.1中国福建泉州/电信0%2ms
210.254.94.5运营商内网14%2ms
3——100%—
10117.24.2.161泉州电信 AS1337760%7ms
1127.152.191.5泉州电信 AS13377699%8ms
12——100%—
13202.97.57.145骨干网/电信 AS413487%21ms
14202.97.12.206骨干网/电信 AS413497%24ms
15202.97.59.62骨干网/电信 AS413412%207ms
1681.173.18.74欧洲/电信 AS413412%215ms
19104.21.6.247Cloudflare AS13335(目标)10%196ms

这张表里有三处”自相矛盾”的地方,正是它们救了这次判断:

  1. 丢包 99% 的那一跳,延迟反而特别漂亮。第 11 跳最快 8ms、最慢 8ms、平均 8ms;第 14 跳更整齐,四个值全是 24ms。链路真丢包时伴随的是排队和延迟抖动,不会是”漏回来的包一个比一个准时”。
  2. 第 12 跳 100% 丢包,可第 13、14 跳还在回话。如果路径真在第 12 跳断了,后面的跳不可能有回包。100% 只代表”这台设备压根不打算理你”。
  3. 末跳只丢 10%。第 19 跳的 IP 104.21.6.247 就是目标本身,它丢 10%、平均 196ms——站点是通的。

真正值得留意的其实是第 15 跳:延迟从 24ms 一步跳到 207ms,而且是离开电信骨干网(AS4134)之后。这不是丢包,是出境绕路——报文从泉州走到电信国际出口,再绕经电信的境外节点(表里标注为”欧洲/电信”,地理位置仅供参考),最后交给 Cloudflare 的 Anycast 边缘。上一篇测到的”全国平均 233ms”就是这么来的:绕路,而不是链路损坏。

为什么中间跳会”丢包”:控制平面 vs 转发平面#

控制平面与转发平面示意:转发平面用 ASIC 线速转发真实流量,控制平面用 CPU 生成 ICMP 并被限速

要读懂这些数字,得先接受一个事实:路由器不是一台电脑,它至少有两套干活的方式。

  • 转发平面(Forwarding Plane):拆包头、查路由表、把包从某个口扔出去。这件事由专用芯片(ASIC / NP)完成,线速运行,你的网页请求、API 调用、视频流全走这条路。
  • 控制平面(Control Plane):跑路由协议、维护转发表,以及处理各种”需要 CPU 想一想”的杂事。生成 ICMP 错误报文,就属于这一类。

traceroute 的原理是发出 TTL 依次为 1、2、3… 的探测包,逼路径上第 N 台路由器把 TTL 减到 0,然后由它生成一个 ICMP Time Exceeded 报文(RFC 792 定义)回给你。关键在于:这个 ICMP 属于”额外劳动”,和转发你的数据没有任何关系。

而一台骨干路由器面对的是整个互联网。全世界每时每刻都有人在探测它,如果它对每个 TTL 超时的包都老老实实生成 ICMP,CPU 会被这种毫无价值的活打满。所以运营商和设备厂商的通行做法是给 ICMP 生成限速:Cisco 上有 ip icmp rate-limit unreachable 这类命令,运营商侧普遍部署 CoPP(Control Plane Policing)策略;IETF 的 ICMP 过滤建议 也把”限速”列为推荐手段。

结果就是:traceroute 里的”丢包率”,统计的是这台路由器愿意回 ICMP 的比例,而不是它转发你数据时丢包的比例。 第 11 跳的 99% 只是说”100 个探测包它只回了 1 个”;第 14 跳的 97% 也只是说”它只回了 3 个”。

区分限速和真丢包,最省事的办法是看被限速那一跳漏回来的包的延迟:

  • 控制平面限速:漏回来的包延迟低且稳(本例 8ms / 21ms / 24ms,最快最慢几乎一样)。因为链路根本不堵,只是路由器懒得理你。
  • 真拥塞:延迟明显抬高,而且最快 / 最慢 / 平均三个值会拉开很大差距——排队是随机的。

我自己电脑上那次更离谱的误读#

讲完别人的数据,说说我在自己机器上踩的坑。为了给这篇文章配一张本机 tracert 的图,我在 Windows 上跑了:

tracert -d blog.juluo.work

本机 tracert -d blog.juluo.work 的真实输出:只有一跳,而且第一跳直接就是目标 IP

只出来一跳,而且第一跳就是目标 IP。

换 tracert -d 8.8.8.8、tracert -d www.baidu.com,一样只有一跳。原因不在运营商,在我自己机器上:我开着 TUN 模式的代理,route print -4 里两条默认路由,走 TUN 网卡(198.18.0.0/15 那段,metric 0)的那条优先级更高,所有流量——包括 ICMP 探测包——都在本地被代理栈接管了。测量点在代理里面,测出来的自然不是真实路径。

顺手做的另外两个测试同样不可信:

ping -n 20 blog.juluo.work

本机 ping -n 20 blog.juluo.work:20 个包丢 9 个,45% 丢包,但成功的那 11 个延迟稳定在 275~287ms

20 个包丢 9 个,45% 丢包。拿着这张图去问人,大概率会得到”你的服务器在丢包”的答案。但看仔细一点:成功的 11 个包,最快 275ms、最慢 287ms,极差只有 12ms。这种”丢得厉害、延迟却极其稳定”的组合,和前面第 11 跳是同一类现象——限速,而不是拥塞。

最能说明问题的是第三个测试。我写了个二十来行的 Python 脚本,对 blog.juluo.work:443 连续建立 20 次 TCP 连接:

import socket
import statistics
import time

HOST = "blog.juluo.work"
PORT = 443
N = 20

ok = 0
times = []
for i in range(1, N + 1):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(5)
    t0 = time.perf_counter()
    try:
        s.connect((HOST, PORT))          # 只做三次握手,不发业务数据
        dt = (time.perf_counter() - t0) * 1000
        times.append(dt)
        ok += 1
        print(f"{i:2d}  TCP {PORT} connect OK   {dt:7.1f} ms")
    except Exception as e:
        print(f"{i:2d}  TCP {PORT} connect FAIL {e}")
    finally:
        s.close()
    time.sleep(0.2)

print(f"\nsuccess = {ok}/{N}, failed = {N - ok}")
print(f"min = {min(times):.1f} ms, avg = {statistics.mean(times):.1f} ms, max = {max(times):.1f} ms")

本机对 blog.juluo.work:443 连 20 次的真实输出:20/20 全部成功,最快 1.0ms、平均 12.4ms

20 次全部成功,最快 1.0ms。

1.0ms 是什么概念?从本机到最近的中国香港机房,物理距离在 1000 公里以上,光在光纤里跑一趟就要 5ms 起步,往返一次 10ms 打底,一次 TCP 握手(SYN → SYN-ACK → ACK)不可能 1ms 完成。这个数字唯一合理的解释是:连接被本机代理栈直接终结了——代理先替远端回掉 SYN,再去慢慢建真正的连接。也就是说,这场测试测的是我的代理,不是我的博客。

警告

这三组本机数据我照样放进文章,但它们的结论是反的:它们证明的是”在带 TUN 代理的机器上做网络测量,结果基本不可用”。排查网络问题时,先确认自己的测量点在哪一层,比多测几次更重要。

判据表:什么时候该管#

把上面这些现象整理成一张表,下次再遇到”中间跳丢包”可以直接对照:

你看到的现象大概率是什么要不要管
中间某跳 90%+ 丢包,但漏回来的包延迟低且稳定控制平面对 ICMP 限速不用管
中间跳 100% 丢包(连 IP 都不显示)设备被配置为不响应 TTL 超时(沉默设备)不用管,看它后面的跳有没有回包
中间跳丢包,同时该跳延迟明显抬高、最快最慢差距很大可能是真拥塞,也可能是限速叠了偶发排队先观察,最终按末跳定论
末跳(目标 IP 自己)持续丢包 > 5%,且延迟抖动明显真丢包:边缘节点异常或链路拥塞要管
从某一跳开始延迟阶梯式上升(如 24ms → 207ms)路由绕路 / 出境,不是丢包想优化延迟才管
只有 ICMP 丢包,TCP 业务正常(页面能开、SSH 不断)ICMP 被策略丢弃或限速不用管
ICMP 和 TCP 同时丢,并且有用户报障真故障立刻管

配套的三条实操建议:

  1. 以末跳为准。中间跳只提供”路径长什么样”的信息;能不能通,只看最后一跳是不是目标 IP、有没有回包。Windows 自带的 tracert 每跳只发 3 个包,样本太少,看丢包率基本没有意义。
  2. 多打几次、多换源。每跳发 100 个包的 mtr 式工具(tcptest.cn 的路由追踪就是这种)比 tracert 可靠得多。换一个检测点再看:如果只有部分中间跳丢、末跳一致正常,基本可以定性为限速。
  3. 直接问业务端口。TCP 握手能否成功、TTFB 多少,才是用户真正感知到的东西。ICMP 只是尽力而为的旁证,从来不是指标。

那这次到底要不要管#

不必。

  • 末跳丢包 10%、平均 196ms,目标可达,业务侧 TCP 连接正常;
  • 87%99% 的那几跳,延迟只有 2124ms,是最典型的控制平面限速特征,没有任何拥塞迹象;
  • 唯一真实存在的问题,是第 15 跳之后从 24ms 涨到 207ms 的出境绕路——这属于 Cloudflare 免费套餐 + Anycast 的固有代价,和”丢包”是两件事,上一篇已经算过这笔账,暂时不动它。

小结#

  • traceroute 的”丢包率”是 ICMP 回包率,不是转发丢包率。中间跳丢 99%,和你的网页能不能打开没有直接关系。
  • 区分限速与真丢包的关键:漏回来的包延迟是否正常。延迟低而稳 = 限速;延迟高而抖 = 拥塞。
  • 只有末跳(目标自己)持续丢包,才轮到”该管”这两个字。
  • 测量前先看自己的测量点在哪一层:一个 TUN 代理就能让 traceroute 只剩一跳,让 TCP 握手变成 1ms。
提示

数据与截图说明:多节点路由追踪数据为 2026-10-05 晚在 tcptest.cn 实测(福建泉州电信节点,每跳 100 个包,完整结果见上面的 tcptest.cn 路由追踪结果);本机 tracert、ping -n 20 与 TCP 连接测试均为同一晚在本机执行的真实输出,未做任何改动。由于本机 TUN 代理会让 tracert 只剩一跳,原计划做的”本机多目标 tracert 对比”拿不到任何中间跳数据,中间跳的分析因此改用 tcptest.cn 的节点侧追踪结果。

同属「工具输出怎么读」的另一篇是 SSL Labs 评分:一个看网络路径,一个看 HTTPS 配置。

这篇文章是否对你有帮助?

发现错误或想要改进这篇文章?

在 GitHub 上编辑此页

文章修订历史 (1 次)

查看变更记录
10月24日 23:18:07 c20be15

docs(baseline): 第 30 轮终检——数字更新到最终状态,补第 28~30 轮小结

中间跳丢包 90% 需要管吗:一次 traceroute 误读的完整拆解
作者
peroe
发布于
10月5日 22:05
许可协议
CC BY-NC-SA 4.0

相关文章