TCP通过维护一个拥塞窗口cwnd来进行拥塞控制
拥塞控制的原则是,只要网络中没有出现拥塞,拥塞窗口的值就可以再增大一些,以便把更多的数据包发送出去,但只要网络出现拥塞,拥塞窗口的值就应该减小一些,以减少注入到网络中的数据包数
TCP拥塞控制算法发展的过程中出现了如下几种不同的思路:
基于丢包的拥塞控制:将丢包视为出现拥塞,采取缓慢探测的方式,逐渐增大拥塞窗口,当出现丢包时,将拥塞窗口减小,如Reno、Cubic等。
基于时延的拥塞控制:将时延增加视为出现拥塞,延时增加时增大拥塞窗口,延时减小时减小拥塞窗口,如Vegas、FastTCP等。
基于链路容量的拥塞控制:实时测量网络带宽和时延,认为网络上报文总量大于带宽时延乘积时出现了拥塞,如BBR。
基于学习的拥塞控制:没有特定的拥塞信号,而是借助评价函数,基于训练数据,使用机器学习的方法形成一个控制策略,如Remy。
拥塞控制算法的核心是选择一个有效的策略来控制拥塞窗口的变化,有几种经典方法:
1、Vegas
Vegas将时延RTT的增加作为网络出现拥塞的信号,RTT增加,拥塞窗口减小,RTT减小,拥塞窗口增加。具体来说,Vegas通过比较实际吞吐量和期望吞吐量来调节拥塞窗口的大小,期望吞吐量:Expected = cwnd / BaseRTT,实际吞吐量:Actual = cwnd / RTT,diff = (Expected-Actual) * BaseRTT,BaseRTT是所有观测来回响应时间的最小值,一般是建立连接后所发的第一个数据包的RTT,cwnd是目前的拥塞窗口的大小
Vegas定义了两个阈值a,b,当diff > b时,拥塞窗口减小,当a <= diff <=b时,拥塞窗口不变,当diff < a时,拥塞窗口增加
Vegas算法采用RTT的改变来判断网络的可用带宽,能精确地测量网络的可用带宽,效率比较好。但是,网络中Vegas与其它算法共存的情况下,基于丢包的拥塞控制算法会尝试填满网络中的缓冲区,导致Vegas计算的RTT增大,进而降低拥塞窗口,使得传输速度越来越慢,因此Vegas未能在Internet上普遍采用
适用场景:适用于网络中只存在Vegas一种拥塞控制算法,竞争公平的情况
2、Reno
Reno将拥塞控制的过程分为四个阶段:慢启动、拥塞避免、快重传和快恢复,是现有的众多拥塞控制算法的基础,下面详细说明这几个阶段
慢启动阶段,在没有出现丢包时每收到一个ACK就将拥塞窗口大小加一(单位是MSS,最大单个报文段长度),每轮次发送窗口增加一倍,呈指数增长,若出现丢包,则将拥塞窗口减半,进入拥塞避免阶段;当窗口达到慢启动阈值或出现丢包时,进入拥塞避免阶段,窗口每轮次加一,呈线性增长;当收到对一个报文的三个重复的ACK时,认为这个报文的下一个报文丢失了,进入快重传阶段,立即重传丢失的报文,而不是等待超时重传;快重传完成后进入快恢复阶段,将慢启动阈值修改为当前拥塞窗口值的一半,同时拥塞窗口值等于慢启动阈值,然后进入拥塞避免阶段,重复上诉过程
Reno算法将收到ACK这一信号作为拥塞窗口增长的依据,在早期低带宽、低时延的网络中能够很好的发挥作用,但是随着网络带宽和延时的增加,Reno的缺点就渐渐体现出来了,发送端从发送报文到收到ACK经历一个RTT,在高带宽延时(High Bandwidth-Delay Product,BDP)网络中,RTT很大,导致拥塞窗口增长很慢,传输速度需要经过很长时间才能达到最大带宽,导致带宽利用率将低
适用场景:适用于低延时、低带宽的网络
3.1、BIC
BIC算法对窗口可能的最大值进行二分查找,它基于以下的事实:
1、如果发生丢包的时候,窗口的大小是W1,那么要保持线路满载却不丢包,实际的窗口最大值应该在W1以下;
2、如果检测到发生丢包,并且已经将窗口乘性减到了W2,那么实际的窗口值应该在W2以上 因此,在TCP快速恢复阶段过去之后,便开始在W2~W1这个区间内进行二分搜索,寻找窗口的实际最大值。于是定义W1为Wmax,定义W2为Wmin 而整个二分搜索的过程采用ACK驱动:每收到一个ACK的时候,便将窗口设置到Wmax和Wmin的中点,一直持续到接近Wmax。可见BIC的行为是ACK驱动的,而ACK在什么时候到来是与RTT相关的 BIC算法已经在没有丢包的情况下无限接近了Wmax,这意味着带宽有空闲资源了,此次的最大带宽已经不止Wmax了,而是大于Wmax的一个值
1、怎么发现已找到最大带宽:因为往这之后就会发生丢包;
2、怎么找到最大带宽:如果度过了Wmax都没有丢包,说明新的Wmax还没有达到,此时BIC采取了一种非常简单直接的方法:按照逼近Wmax的路径倒回去,即采用与之对称的方案
BIC算法的问题:
两个RTT不同的连接,其通过BIC算法搜索到Wmax的时间是不同,进而其进入Max-Probe阶段也是不同的,因此空闲的带宽会被RTT短的那个连接无情的占有
即公平性的问题:TCP对带宽的利用并不公平;这是一个,抢占带宽的算法
3.2、Cubic
Cubic是Linux内核2.6之后的默认TCP拥塞控制算法,使用一个立方函数(cubic function)作为拥塞窗口的增长函数,其中,C是调节因子,t是从上一次缩小拥塞窗口经过的时间,Wmax是上一次发生拥塞时的窗口大小,β是乘法减小因子。从函数中可以看出拥塞窗口的增长不再与RTT有关,而仅仅取决上次发生拥塞时的最大窗口和距离上次发生拥塞的时间间隔值
Cubic拥塞窗口增长曲线如下,凸曲线部分为稳定增长阶段,凹曲线部分为最大带宽探测阶段。如图2所示,在刚开始时,拥塞窗口增长很快,在接近Wmax口时,增长速度变的平缓,避免流量突增而导致丢包;在Wmax附近,拥塞窗口不再增加;之后开始缓慢地探测网络最大吞吐量,保证稳定性(在Wmax附近容易出现拥塞),在远离Wmax后,增大窗口增长的速度,保证了带宽的利用率
当出现丢包时,将拥塞窗口进行乘法减小,再继续开始上述增长过程。此方式可以使得拥塞窗口一直维持在Wmax附近,从而保证了带宽的利用率
Cubic算法的优点在于只要没有出现丢包,就不会主动降低自己的发送速度,可以最大程度的利用网络剩余带宽,提高吞吐量,在高带宽、低丢包率的网络中可以发挥较好的性能
但是,Cubic同之前的拥塞控制算法一样,无法区分拥塞丢包和传输错误丢包,只要发现丢包,就会减小拥塞窗口,降低发送速率,而事实上传输错误丢包时网络不一定发生了拥塞,但是传输错误丢包的概率很低,所以对Cubic算法的性能影响不是很大
Cubic算法的另一个不足之处是过于激进,在没有出现丢包时会不停地增加拥塞窗口的大小,向网络注入流量,将网络设备的缓冲区填满,出现Bufferbloat(缓冲区膨胀)。由于缓冲区长期趋于饱和状态,新进入网络的的数据包会在缓冲区里排队,增加无谓的排队时延,缓冲区越大,时延就越高。另外Cubic算法在高带宽利用率的同时依然在增加拥塞窗口,间接增加了丢包率,造成网络抖动加剧
适用场景:适用于高带宽、低丢包率网络,能够有效利用带宽
4、BBR
BBR是谷歌在2016年提出的一种新的拥塞控制算法,目前已经集成到Linux 4.9以上版本的内核中
BBR算法不将出现丢包或时延增加作为拥塞的信号,而是认为当网络上的数据包总量大于瓶颈链路带宽和时延的乘积时才出现了拥塞,所以BBR也称为基于拥塞的拥塞控制算法。BBR算法周期性地探测网络的容量,交替测量一段时间内的带宽极大值和时延极小值,将其乘积作为作为拥塞窗口大小(交替测量的原因是极大带宽和极小时延不可能同时得到,带宽极大时网络被填满造成排队,时延必然极大,时延极小时需要数据包不被排队直接转发,带宽必然极小),使得拥塞窗口始的值始终与网络的容量保持一致
由于BBR的拥塞窗口是精确测量出来的,不会无限的增加拥塞窗口,也就不会将网络设备的缓冲区填满,避免了出现Bufferbloat问题,使得时延大大降低。如图4所示,网络缓冲区被填满时时延为250ms,Cubic算法会继续增加拥塞窗口,使得时延持续增加到500ms并出现丢包,整个过程Cubic一直处于高时延状态,而BBR由于不会填满网络缓冲区,时延一直处于较低状态
由于BBR算法不将丢包作为拥塞信号,所以在丢包率较高的网络中,BBR依然有极高的吞吐量
BBR算法是反馈驱动的,有自主调节机制,不受TCP拥塞控制状态机的控制,通过测量网络容量来调整拥塞窗口,发送速率由自己掌控,而传统的拥塞控制算法只负责计算拥塞窗口,而不管发送速率(pacing rate),怎么发由TCP自己决定,这样会在瓶颈带宽附近因发送速率的激增导致数据包排队或出现丢包
BBR算法的不足之处在于设备队列缓存较大时,BBR可能会竞争不过Cubic等比较激进算法,原因是BBR不主动去占据队列缓存,如果Cubic的流量长期占据队列缓存,会使得BBR在多个周期内测量的极小RTT增大,进而使BBR的带宽减小
适用场景:适用于高带宽、高时延、有一定丢包率的长肥网络,可以有效降低传输时延,并保证较高的吞吐量
5、Remy
Remy也称为计算机生成的拥塞控制算法,采用机器学习的方式生成拥塞控制算法模型。通过输入各种参数模型(如瓶颈链路速率、时延、瓶颈链路上的发送者数量等),使用一个目标函数定量判断算法的优劣程度,在生成算法的过程中,针对不同的网络状态采用不同的方式调整拥塞窗口,反复修改调节方式,直到目标函数最优,最终会生成一个网络状态到调节方式的映射表,在真实的网络中,根据特定的网络环境从映射表直接选取拥塞窗口的调节方式
Remy试图屏蔽底层网络环境的差异,采用一个通用的拥塞控制算法模型来处理不同的网络环境。这种方式比较依赖输入的训练集(历史网络模型),如果训练集能够全面覆盖所有可能出现的网络环境及拥塞调节算法,Remy算法在应用到真实的网络环境中时能够表现的很好,但是如果真实网络与训练网络差异较大,Remy算法的性能会比较差
适用场景:网络环境为复杂的异构网络,希望计算机能够针对不同网络场景自动选择合适的拥塞控制方式,要求现有的网络模型能够覆盖所有可能出现情况