logo NodeSeekbeta

ECMP 科研2:po0上海 -> po0香港の沪港优化

前言:https://www.nodeseek.com/post-911105-1

发现一个有意思的现象,po0 上海到 po0 香港 ping 延迟稳定,但是 mtr tcp 模式就是多条路径负载均衡,实际测试结果如下:

image

不过 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 不同环境测试结果可能不同,此测试结果仅适用于我这里的机器。

  • 再研究下去就到量子力学了 至于吗....几毫秒而已...

  • 爱折腾

  • 支持研究精神

  • 流弊

  • 你是这个👍

  • 不知道广港怎么样,这个对游戏党很有用

  • 火钳留明

  • 这都能发现 xhj005

你好啊,陌生人!

我的朋友,看起来你是新来的,如果想参与到讨论中,点击下面的按钮!

📈用户数目📈

目前论坛共有72567位seeker

🎉欢迎新用户🎉