您现在的位置是:首页 >技术教程 >scalable tcp 的扩展性和公平性网站首页技术教程
scalable tcp 的扩展性和公平性
高效的 TCP 拥塞控制算法在连接生命周期中做下面的循环:
- 尽快找到饱和点。
- 快速逼近饱和点。
- 在饱和点尽可能久停留后 probe,回到第 1 步。
CUBIC 用下凸曲线实现 1,用上凸曲线实现 2,上凸和下凸的拐点附近斜率很小,这部分尽可能长,实现尽量停留,此外,CUBIC 曲线的表达式确保 BDP 越大,逼近饱和点的速度越快,由此实现 BDP 可扩展,对于快速 probe,CUBIC 可自适应 BDP 的变化,理论上这是一个非常优秀的算法。
事实上,Reno 的 AIMD 足以解决拥塞崩溃问题,但这是一个绝对可靠但也绝对低效的算法,后续几乎所有 cc 都在针对性解决 Reno 这样那样的问题,从 NewReno 开始一直到 BBR,包括各路水论文野算法,无一例外,但却少有像 CUBIC 综合表现都很均衡的。
针对 Reno 在长肥管道恢复慢的问题,一系列算法被提出,scalable tcp 是个典型。本文简述它。scalable tcp 算法很简单:
- 非丢包每收到一个 ACK:cwnd = cwnd + a
- 检测到丢包:cwnd = b * cwnd
每个 ACK 后 cwnd 增加固定额度 a,在一个 RTT 内, cwnd 个 ACK 则增窗 a * cwnd,和前一个 RTT 相比:
c w n d n + 1 = ( 1 + a ) ∗ c w n d n cwnd_{n+1}=(1+a)∗cwnd_n cwndn+1=(1+a)∗cwndn
可见,scalable tcp 是一个 MIMD 算法,cwnd 指数增长,而 MIMD 是不收敛的,scalable tcp公平性就是一大问题,但可以将此理解为 scalable tcp 的代价,换来了它顾名思义的 “可扩展”。
Reno 之所以不可扩展,因为 AIMD 周期和 Wmax 正相关,而 Wmax 也和 BDP 正相关,这意味着 BDP 越大,AIMD 周期越久,以 a = 1,b = 0.5 的 Reno-AIMD 为例,一个周期需要 0.5 * Wmax 个 RTT,BDP 越大,Wmax 越大,可能本来 RTT 就很长,于是恢复到 Wmax 的时间越久,时间越久,遭遇新丢包概率越大,恢复到 Wmax 越不易,好不容易到达饱和,buffer 溢出,一切从头开始。
再看 scalable tcp 如何可扩展。
scalable tcp 在一个 MIMD 周期内需要将 cwnd 从 b * Wmax 恢复到 Wmax,总量为 (1 - b) * Wmax。设从 b * Wmax 开始经过 x 个 RTT 可完成,于是 ( 1 + a ) x ∗ W m a x = W m a x (1+a)x∗W_{max}=W_{max} (1+a)x∗Wmax=Wmax ,解得 x = − log 1 + a b x=−log_{1+a}b x=−log1+ab
x 为常数,经过常数个 RTT 即可恢复,与 BDP 无关,这就是可扩展性。
scalable tcp 曲线和 Reno 曲线在不同 BDP 的对比参见:Scalable TCP
虽然 scalable tcp 无数小锯齿的总面积(表示 W 的积分,即发送数据量)与 Reno 的一个大锯齿面积相等,但那只是现实中不易达的理论场景,防的就是夜长梦多,上面提到 “恢复到 Wmax 的时间越久,遭遇丢包概率越大,恢复到 Wmax 越不易”,这是缓慢响应的弊端,而 scalable tcp 解决了这个问题。
但必须认识到,x 的单位是 “个 RTT”,x * RTT 与 RTT 成正比,如果 RTT 本身很大,这段时间也不会小,好在 RTT 最多也就 200ms 级,倒也不是大碍。
tcp scalable 应该是实现最简单的算法,Linux kernel 的 scalable 实现算上注释一共 64 行,不算注释 46 行:kernel/net/ipv4/tcp_scalable.c
随着硬件和底层网络技术的发展(比如 LTE,Wi-Fi 7),算法将越来越不重要,现在做 TCP 优化的唯一意义在于还要给这行业的工人发工资,等这些人都财务自由了,也许就可以从线上撤掉这类优化算法了。就好像零几年时都在叫 Java 性能不如 C/C++,但现在即使 Java 还是不如 C/C++ 快,也没人叫了,因为硬件已经让两者非常接近了,没有必要投入资源去优化了。遇到需要优化的东西,除了立马优化,还可以等,时间可以优化一切。不如返璞归真,看些老算法,本文科普 scalable tcp。
浙江温州皮鞋湿,下雨进水不会胖。