4.6 TCP CUBIC
Last updated
Last updated
到目前为止大家应该已经清楚,拥塞控制算法的核心在于找到合适的向网络发送数据的速率,而这很容易出错。如果发送太少的数据,那网络利用率就比较低,进而导致应用程序性能较差。发送太多的数据,网络又会变得拥塞,最坏情况下会完全堵死网络,导致所有人都无法正常使用。对比这两种情况,发送太多数据更加糟糕,因为拥塞情况下会导致丢包,丢包之后会重传,而在相同数据量的情况下,重传会让问题变得更加糟糕。前面介绍的集成于 Tahoe,Reno和 NewReno 的 AIMD也是基于这种考虑:慢慢的增加窗口大小(加法递增)但是快速的减小窗口(乘法递减),这样才能在网络堵死之前恢复过来。
AIMD 的策略可以说没有错,但是随着计算机网络的发展,链路带宽越来越大(10Mbps-100Gbps),相应的带宽延时积也越来越大。越高的带宽延时积需要越大的拥塞窗口(确切的说是 EffectiveWindow),才能充分利用链路,而这个时候 AIMD 的保守增加拥塞窗口就显得非常低效了,因为在真正填满线路前,可能需要等待多个 RTT 时间。所以对于如何探测合适的拥塞窗口大小,又涌现了一些新的方法。
其中一种方法称为 Binary Increase Congestion Control(BIC),它认为拥塞窗口在某些时候可以快速加大,在某些时候又需要慢慢的加大。类似的想法在TCP Reno 中也存在,TCP Reno在最开始会指数级增加窗口大小,之后再突然的转变成线性增加。而 BIC 选择通过二分查找的方法来找到“正确”的窗口大小。在丢包之后,拥塞窗口按照乘法因子β进行缩减。每当一个窗口内的 packet 都成功发送了,拥塞窗口会变成当前值和触发拥塞时的旧值的中点。这样的话,拥塞窗口渐进的向旧的拥塞窗口靠近:开始很快,然后很慢。(极端情况下,窗口值可能永远达不到原来的值,详见Zeno 悖论。所以当窗口达到特定的阈值时,它就会被设置为原来的值)
此时,如果仍然没有发现拥塞,我们可以认为网络状况比丢包时变得更好了,所以此时可以尝试探测更大的拥塞窗口大小。对于更大的拥塞窗口的探测,BIC 算法开始会慢慢探测,后面逐渐变快。你可以从图 28 大致看到 BIC 是如何增加其窗口。其中 Wmax是上次丢包时旧的拥塞窗口大小。
BIC 最终进化成了一个新的变种,CUBIC。CUBIC 如今是 Linux 中的默认的拥塞控制算法。相比 BIC,CUBIC 有很多改进:
用一个平滑的 cubic 函数(注,立方函数)来替代 BIC 中的分段线性函数。
根据上一次拥塞事件(例如,收到一个重复 ACK)流逝的时间来调整拥塞窗口,而不是像 BIC 一样根据收到 ACK 来调节。因为 ACK 受 RTT 影响,这样短 RTT 连接可以更加频繁的收到 ACK,进而更快的恢复窗口。CUBIC 的这个改进可以使得长 RTT 的连接更公平的与短 RTT 的连接进行竞争(注,假设你从电脑同时下载同城市的文件和下载跨国服务器的文件,当在某个瓶颈链路发生拥塞时,如果采用 BIC 算法,同城市的TCP 连接更快恢复拥塞窗口,会占用瓶颈链路更多的带宽)。这是与之前 TCP 版本一个有趣的不同点,在之前的版本中,短 RTT 的 TCP 连接在共享一个瓶颈链路时明显会有优势。
图 28 中展示的立方函数有三个阶段:快速增加,平稳调节,继续快速增加。这里的初始目标 Wmax就是上次拥塞事件发生时拥塞窗口的大小。你可以看到窗口大小开始增长的很快,但是当接近 Wmax 时就慢下来了;之后当刚刚超越 Wmax 时,窗口的增长会小心的增长;最后会快速尝试探测一个新的 Wmax。
刚刚说到,CUBIC 会基于上次拥塞事件过去的时间来计算拥塞窗口(CongestionWindow
)的大小。
其中
C 是缩放比例,β是乘法递减因子。CUBIC 将β设置成0.7,而不是其他 TCP 版本中的 0.5。通过图 28 可以看出,CUBIC会从凹函数转变成凸函数,而之前 TCP 版本中增加窗口只有凸函数。
有趣的是,相比之前版本的 TCP,CUBIC在不同的场景下要么更加激进,要么更保守。短 RTT 的TCP Reno 连接更可能获得瓶颈链路的带宽,所以 CUBIC 引入了一种“TCP 友好”的模式使其变得与 TCP Reno 一样激进(注,我也没懂这句话作者想表达什么)。但是在其他清况下,尤其是在高带宽延时网络中,CUBIC 更可能获得瓶颈链路更多的带宽,因为 CUBIC 更快的增加其窗口大小。这让我们重新思考 3.3 中讨论过的,“公平性”是否是一个正确的设计目标。最终,CUBIC 被充分的分析,并且在多个场景展示了很好的性能的同时也没有带来不必要的破坏,所以它已经被广泛的部署。
更多阅读:S. Ha, I. Rhee, and L. Xu. CUBIC: a New TCP-friendly High-speed TCP Variant. ACM SIGOPS Operating Systems Review, July 2008