各种TCP拥塞控制算法

6,104 阅读7分钟

前言

自从TCP拥塞控制的概念提出以来,TCP拥塞控制算法经历了一系列的演化。这里根据网上的资料大致总结一下各个TCP拥塞控制算法。

TCP Tahoe/Reno

最初的实现,包括慢启动、拥塞避免两个部分。基于重传超时(retransmission timeout/RTO)和重复确认为条件判断是否发生了丢包。两者的区别在于:Tahoe算法下如果收到三次重复确认,就进入快重传立即重发丢失的数据包,同时将慢启动阈值设置为当前拥塞窗口的一半,将拥塞窗口设置为1MSS,进入慢启动状态;而Reno算法如果收到三次重复确认,就进入快重传,但不进入慢启动状态,而是直接将拥塞窗口减半,进入拥塞控制阶段,这称为“快恢复”。

而Tahoe和Reno算法在出现RTO时的措施一致,都是将拥塞窗口降为1个MSS,然后进入慢启动阶段。

TCP Vegas

TCP Vegas算法由 Lawrence Brakmo 和 Larry L. Peterson 在1994年提出,它和其他拥塞控制算法的不同之处在于Vegas算法并不急于丢包来判断是否发生了拥塞,而是通过数据包延迟来判断。Vegas通过RTT(roundtrip time)来决定增加或者减小拥塞窗口,它能够拥塞将要发生时就避免拥塞,而不是等到拥塞已经发生之后再减小发送速度,因此能够减小重传和超时的几率。Vegas算法与其他算法(比如Reno)共存时,会由于比其他算法更先降低发送速率而出现公平性问题。

TCP New Reno

TCP New Reno主要改进了TCP Reno中快速恢复阶段的重传。

在Reno的快恢复中,一旦出现3次重复确认,TCP发送方会重发数据包并设置定时器等待该重发数据包被确认。当重发的数据包被确认后,就立即退出快速恢复阶段,进入拥塞控制阶段。但如果一次拥塞中出现多个丢包,Reno会误以为发生了多次拥塞而重复减小拥塞窗口导致发送速率下降。

而在New Reno的快速恢复中,一旦出现3次重复确认,会记下出现重复确认时未确认的数据包的最大序列号,然后重发重复确认的数据包。如果有多个数据包丢失,则继续重发丢失的数据包,知道最大序列号的数据包被确认才推出快恢复阶段。

New Reno在低错误率时运行效率和“选择确认”(Selective ACKnowledgement,SACK)相当,在高错误率仍优于Reno。

TCP BIC/CUBIC

TCP BIC(Binary Increase Congestion control)旨在优化高速高延迟网络(即“长肥网络”(long fat network,LFN))的拥塞控制,其拥塞窗口算法使用二分搜索算法尝试找到能长时间保持拥塞窗口最大值的值。Linux内核在2.6.8至2.6.18使用该算法作为默认TCP拥塞算法。

BIC算法采用二分查找的方式来确定最大的窗口大小:如果发生丢包时窗口大小是W1,那么最大窗口Wmax应该小于W1;这时将窗口缩小到W2(乘以一个系数,也就是乘法减小),那么可以预期W1>Wmax>W2;这时再将窗口大小设置为(W1+W2)2(也就是二分查找),即每收到一个ACK就把窗口大小设置为两个界限的中点。

如果窗口大小已经无限逼近W1,说明网络状况又变好了(可用带宽增加了),这时BIC会尝试往上寻找更大的Wmax。而在往上寻找时,BIC会镜像的利用逼近当前Wmax的路径去搜寻,也就是前面是如何先快后慢慢地靠近当前Wmax的,后面就反过来先慢后快地增长。

而CUBIC则是比BIC更温和和系统化的分支版本,其使用三次函数代替二分算法作为其拥塞窗口算法(因为实际上BIC的搜索曲线看起来就像一个三次函数,所以干脆就写一个三次函数来模拟曲线),并且使用函数拐点作为拥塞窗口的设置值。Linux内核在2.6.19后使用该算法作为默认TCP拥塞算法。

TCP Westwood/Westwood+

TCP Westwood改良自New Reno,不同于以往其他拥塞控制算法使用丢失来测量,其通过对确认包测量来确定一个“合适的发送速度”,并以此调整拥塞窗口和慢启动阈值。Westwood改良了慢启动阶段算法为“敏捷探测(Agile Probing)”,并且设计了一种持续探测拥塞窗口的方法来控制进入“敏捷探测”,使连接尽可能地使用更多的带宽。Westwood+使用更长的带宽估计间隔和优化的滤波器来修正Westwood对ACK压缩场景对带宽估计过高的问题。通过以上改良,TCP Westwood系列算法在有线网络和无线网络的拥塞控制上取得平衡,尤其研究中针对于无线通信网络上。

Compound TCP

Compound TCP是微软自己实现的TCP拥塞控制算法,通过同时维护两个拥塞窗口,来实现在长肥网络有较好的性能而又不损失公平性。CTCP维护两个拥塞窗口:一个常规的AIMD(英语:Additive increase/multiplicative decrease)窗口,以及一个基于延迟的窗口,最终实际使用的滑动窗口大小是这两个窗口的和。AIMD窗口与Reno的增加方式相同;如果延迟小,基于延迟的窗口将迅速增加以提高网络的利用率。一旦经历了排队,延迟窗口将逐渐减小以补偿增加的AIMD窗口。这样的目的是保持两者的总和大致恒定,使算法估计带宽时延积的路径。

TCP PRR

TCP PRR(TCP Proportional Rate Reduction )是旨在恢复期间提高发送数据的准确性。该算法确保恢复后的拥塞窗口大小尽可能接近慢启动阈值

TCP BBR

TCP BBR(Bottleneck Bandwidth and Round-trip propagation time)是由Google设计,于2016年发布的拥塞算法。以往大部分拥塞算法是基于丢包来作为降低传输速率的信号,而BBR则基于模型主动探测。该算法使用网络最近出站数据分组当时的最大带宽和往返时间来建立网络的显式模型。数据包传输的每个累积或选择性确认用于生成记录在数据包传输过程和确认返回期间的时间内所传送数据量的采样率。该算法认为随着网络接口控制器逐渐进入千兆速度时,分组丢失不应该被认为是识别拥塞的主要决定因素,所以基于模型的拥塞控制算法能有更高的吞吐量和更低的延迟,可以用BBR来替代其他流行的拥塞算法,例如CUBIC。

总结

可以看出,TCP拥塞控制主要是:1、探测是否出现拥塞;2、出现拥塞时如何反应。

最初的算法是基于丢包来判断是否发生了拥塞,一旦出现拥塞之后就降低发送速率来避免拥塞。后面有出现了基于RTT判断拥塞的算法,但是这种算法会因为太“君子”而提前减小发送速率(让出带宽),从而可能被共存的其他算法进一步压榨产生公平性问题。微软的CTCP通过维护两个窗口来避免这种公平性问题,一个AIMD的窗口来保证不被其他人压榨,另一个基于延迟的窗口能够保证有带宽时能迅速提高来提高带宽利用率。而BBR则直接采用主动探测的方式来判断拥塞是否发生。

当出现拥塞之后,通常需要降低发送速率来避免拥塞进一步加剧,而不同算法在这时的处理都不尽相同,最初的算法通过直接降低发送速率到1来简单处理,但是这种方式太过粗暴,后续的其他算法也都做了不同的尝试。