前言:https://www.nodeseek.com/post-911105-1
发现一个有意思的现象,po0 上海到 po0 香港 ping 延迟稳定,但是 mtr tcp 模式就是多条路径负载均衡,实际测试结果如下:

不过 mtr 出现多个 IP 只能算线索,不能直接说明有 ECMP,有些路由器本来就会用不同接口回 ICMP。真正要验证的是:目标 IP 和目标端口固定,只换 TCP 源端口,RTT 会不会稳定地分成几档?
如果会,说明转发是按 TCP 四元组 hash 的。不同连接会被分到不同路径,那就有"抽卡"选快路径的空间。
于是开始科研。
一、测试 1:随机源端口,建连 100 次
每次新建 socket 连接同一个目标端口,记录 connect 耗时和源端口。
Success: 100/100
Min: 21.18 ms
Median: 25.98 ms
Max: 29.85 ms
StDev: 1.94 ms
同一个目标,建连耗时从 21 ms 到 30 ms,差了将近 9 ms。
不过这还说明不了问题,也可能只是不同时刻的排队和抖动。
二、测试 2:固定源端口,重复测
取 41000~41019 共 20 个源端口,每个端口连 10 次,测试顺序打乱。
| 源端口 | RTT 中位数 | 标准差 |
|---|---|---|
| 41018 | 21.90 ms | 0.03 |
| 41000 | 22.58 ms | 0.04 |
| 41012 | 22.58 ms | 0.03 |
| 41002 | 23.32 ms | 0.04 |
| 41007 | 23.38 ms | 0.02 |
| 41014 | 24.51 ms | 0.04 |
| 41010 | 25.35 ms | 0.04 |
| 41003 | 26.07 ms | 0.03 |
| 41013 | 27.94 ms | 0.04 |
| 41019 | 28.49 ms | 0.03 |
| 41016 | 28.83 ms | 0.04 |
| 41004 | 29.46 ms | 0.04 |
(节选 12 个)
关键在标准差:同一个源端口测 10 次,波动只有 0.02~0.04 ms。例如:
41018 min 21.86 / max 21.97
41004 min 29.39 / max 29.52
同一个端口始终落在同一档,换一个端口就稳定落在另一档。这和"按四元组确定性选路"完全吻合。
三、测试 3:20 条长连接跑 5 分钟
connect 只测了握手。为了确认数据传输阶段也是这样,在香港起一个 TCP Echo(端口 18800),上海同时开 20 条长连接,每条用不同源端口。连接不断开,每秒 echo 一次,同时用 TCP_INFO 读内核 RTT,一共跑 300 秒。
连接数: 20
时长: 300 s
样本: 6000
最快 P50: 21.808 ms
最慢 P50: 29.030 ms
差值: 7.222 ms
| 源端口 | 回显 P50 | 回显 P95 | 内核 RTT P50 |
|---|---|---|---|
| 41014 | 21.808 | 21.931 | 21.766 |
| 41003 | 22.588 | 22.713 | 22.554 |
| 41000 | 22.615 | 22.726 | 22.572 |
| 41012 | 23.423 | 23.510 | 23.394 |
| 41009 | 29.030 | 29.134 | 29.004 |
最快的连接 5 分钟都在 21.8 左右,最慢的一直在 29 左右,P95 和 P50 只差 0.1 ms。
结论:po0 沪港内网里,不同 TCP 四元组之间存在约 7 ms 的稳定延迟分层,而且会一直持续到数据传输阶段。 底层到底是传统 ECMP 还是虚拟网络的其他哈希转发,没有拓扑信息确认不了。但只要快路径能被稳定选中并一直保持,就值得优化。
四、方案:GOST MTCP + ECMP PathLock
思路是先抽到一条快的 TCP,然后让所有业务都复用它:
原则是:启动时积极选路,正常运行时不折腾,真故障才重抽。不会因为 RTT 偶尔升高就把整条业务踢掉,否则上面所有业务都会受影响。
项目地址:https://github.com/zcp1997/gost-ecmp-pathlock
部署过程就不细说了:香港装 Remote(MTCP 监听 6600)。然后在香港把安装脚本和 GOST 打成离线包,改一下脚本让它从本地读文件,再通过内网 FTP 传过去安装。
五、实战选路
第一次:阈值 22 ms,抽 12 次全军覆没
PREWARM_REJECT_SLOW sport=65058 minrtt=24.862
PREWARM_REJECT_SLOW sport=55768 minrtt=25.626
PREWARM_REJECT_SLOW sport=1312 minrtt=24.490
PREWARM_REJECT_SLOW sport=50396 minrtt=22.363
...
PREWARM_KEEP_SLOW sport=54312 minrtt=24.325 attempt=12/12
ANCHOR_BOUND_SLOW
ACCEPT_RTT_MS=22 的含义是严格小于 22。12 次都没抽中,系统进入降级状态:
State: DEGRADED Reason: PATH minRTT: 24.325 ms
Outer: 1 Remote: UP DataPlane: OK
这是设计好的行为:抽不到快路径时保留一条能用的连接,保证业务连通,不会无限重连。
注意第 4 次抽到过 22.363,说明 6600 端口上快档大概在 22.x,22 的门槛设得太严了。
第二次:阈值放到 23 ms,第 3 抽命中
PREWARM_REJECT_SLOW sport=28718 minrtt=25.147 attempt=1/12
PREWARM_REJECT_SLOW sport=5730 minrtt=25.858 attempt=2/12
PREWARM_SUCCESS sport=63972 minrtt=22.502 attempt=3/12
ANCHOR_BOUND sport=63972 cause=GOST_PID_CHANGED
用 ss -tni 看内核状态:
ESTAB sport 63972 -> 6600
bbr rtt:24.523/3.749 minrtt:22.44
内核记录的 minrtt 是 22.44,和 Prewarm 测到的 22.502 对得上,Watchdog 判定为 FAST。
实时平滑 RTT 显示 24.5,并不代表选路失败。阈值判断用的是 minRTT,运行时有排队波动很正常,不会因此重建。
后记
不同 ip 不同环境测试结果可能不同,此测试结果仅适用于我这里的机器。
再研究下去就到量子力学了 至于吗....几毫秒而已...
爱折腾
支持研究精神
流弊
你是这个👍
不知道广港怎么样,这个对游戏党很有用
火钳留明
这都能发现