谈TCP BBR拥塞控制算法

说是tcp拥塞控制,其实也不是,归根到底BBR是协议无关的拥塞控制算法,quic也使用。quic当道,低延迟,高效,适配http2,应用层易部署;而bbr发布前,也已经在google和youtube证明了其在吞吐和延迟上优良的性能,只服务端部署,完美适配需要下行高吞吐低延迟的场景。

标准TCP的问题

基于丢包的拥塞控制算法,来说标准TCP拥塞控制存在的问题。标准TCP将网络丢包的原因归结为拥塞,而忽略链路错误造成的丢包,这在高速网络环境中是不可取的。而传统的拥塞控制算法为了保证其公平性,采用了“加性增乘性减”(AIMD)拥塞控制思想,一旦丢包发生,窗口便被大幅度减少,这使得在存在丢包的高速环境中,即使理论带宽再大,实际带宽最终只能收敛到一个小值。

另一点,关于网络中的bufferbloat问题(缓冲区膨胀,TCPIP卷一中有相关解释)。现代网络中间设备(路由器、防火墙)为解决流量突发问题(短时收速率大于发送速率),都存在较大的流量缓存功能,缓存队列的增加将导致报文RTT变大。传统拥塞控制算法因不具备主动探测能力,为了获取最大带宽,将不断增大窗口大小直至网络缓存饱和,所以它的收敛状态是一个网络缓存饱和的状态,这使得报文延迟巨大。即使在窗口不大的情况下,因为传统算法并不对发送速率做限制,所以小的窗口状态下仍可能因为突发流量使网络缓存饱和。

bbr基础

谈TCP BBR拥塞控制算法_第1张图片
上图展示了rtt、发送速率和发送数据大小的关系:

  • 初始状态下,受发送端数据量较小的限制,RTT始终恒定且保持在一个较小值,带宽随发送数据量的增大线性增长,此时的带宽瓶颈在于发送端;
  • 当到达瓶颈带宽后(即达到网络瓶颈点的发送速率后,需要开始使用网络队列缓存),RTT随着队列缓存的增大而增大,而带宽受瓶颈节点发送速率的限制,也始终维持在一个恒定值,此时的贷款瓶颈在网络中间节点;
  • 当网络队列缓存饱和后,继续增加发送数据,将造成网络丢包。
    对于传统拥塞控制算法来说,其工作点保持在bandwidth-limited右边界的位置,虽然达到了最大带宽,却以巨大的延迟为代价。而对于bbr而言,我们希望其工作在bandwidth-limited的左边界,在保证最大瓶颈带宽(btlBw)的同时,获得最小延迟(RTprop)。

下面看一下bbr对标准TCP问题的解决方式:

  • 不再将丢包作为拥塞判断的一部分。TCP从SACK开始就提出将拥塞控制和选择重传机制分离,bbr也遵循了这一思想。
  • 因为最优带宽和延迟无法同时测量(btlBw的测量会造成存在网络缓存增加RTT,而RTprop的测量要求网络缓存为空),所以分别估计带宽(btlBw)和延迟(RTprop),最后计算出cwnd。同时增加变量pacing rate(btlBw * 增益系数),用于控制发送端的发送速率,以解决发送端突发造成的网络排队问题。

bbr状态机

谈TCP BBR拥塞控制算法_第2张图片

  • STARTUP:
    这是bbr的加速阶段,类似于慢启动阶段,startup以指数的增益速度增加发送速率,希望快速探测到Btlbw瓶颈带宽,这里的增益系数为2/ln2。

    当判断到连续三个往返时间连接的带宽未增加时(提升小于25%),表示瓶颈带宽已到达,STARTUP阶段结束,状态切换至DRAIN阶段。之所以bbr要等待三个往返时间,因为需要确保瓶颈带宽的测量结果不是因为接收方接收窗口限制造成,所以bbr给予三个往返时间保证STARTUP阶段接收窗口可以有机会增大。

    上述的判断条件同时也会引来一些问题,当三个往返时间带宽未增加时,说明瓶颈带宽在之前的某个时间点已经达到,那么这三个往返时间的带宽增加,无疑会增加网络中的报文数量,使网络缓存被填充。所以,bbr在STARTUP状态后进入DRAIN状态,对网络中额外增加的流量进行排空,保证只存在BDP大小的报文在网络中。

  • DRAIN:
    DRAIN阶段存在的意义,是为了排空STARTUP阶段造成的网络缓存,使inflight大小等于BDP。在该阶段,bbr使用一个小的增益系数(STARTUP状态增益系数的倒数)计算pacing rate和cwnd,使得网络队列缓存被迅速排空。

  • PROBE_BW:
    该状态是bbr的一个稳定状态,bbr的大部分时间都在该状态运行,当bbr测量到瓶颈带宽和最小rtt,并且inflight等于BDP后,便开始以一个稳定的匀速维护着网络状态,偶尔小幅提速探测是否有更大带宽,偶尔小幅降速公平的让出部分带宽。这里的幅度即为增益系数,该阶段增益系数如下所示:

    static const int bbr_pacing_gain[] = {
          BBR_UNIT * 5 / 4,    /* probe for more available bw */
          BBR_UNIT * 3 / 4,    /* drain queue and/or yield bw to other flows */
          BBR_UNIT, BBR_UNIT, BBR_UNIT,    /* cruise at 1.0*bw to utilize pipe, */
          BBR_UNIT, BBR_UNIT, BBR_UNIT    /* without creating excess queue... */ 
      };
    

    可见,bbr以八个阶段为一个周期,其中6个阶段都以增益系数为1计算pacing rate,保证稳定的速率;1个阶段增益系数为5 / 4,用于探测更高的可用带宽;1个阶段增益系数为3 / 4,用于对上一阶段增速造成的队列缓存进行消耗。需要注意,PROBE_BW的增益系数只用来计算pacing rate,该阶段的cwnd增益恒定为2。

  • PROBE_RTT:
    bbr在任何状态下都有可能进入PROBE_RTT状态,只要满足条件:在一个时间窗口(min_rtt_win_sec)内未测量到比上周期最小RTT更小或等于的RTT值。如果说之前保留的最小RTT代表无队列缓存时的最小RTT,那么RTT测量值的增加代表着缓存队列的增加,此时bbr认为,网络发生了拥塞,需要进入PROBE_RTT状态对网络进行排空并重新测量RTprop。

    该状态下,cwnd被设置为4个MSS,并对RTT重新测量,持续200ms,超时后,根据网络带宽是否满载决定状态切换为STARTUP或PROBE_BW。
    那么如何判断带宽是否满载?和STARTUP一样,PROBE_RTT状态的带宽满载判断,仍是根据是否三个周期带宽增长未超过25%确定。这里需要注意,RTT和BW的测量并不区分状态,换句话说,bbr的状态不是根据是否测量RTT或BW而定的,并不是只有在PROBE_RTT才会测量RTT,并不是只有在PROBE_BW才会测量BW,无论bbr处于哪个状态,ACK的接收总会触发BW和RTT的测量,并实时更新最大BW和最小RTT,区别在于不同阶段使用不同的增益系数,最后结合不同增益系数计算pacing rate和cwnd。bbr的状态定义更多的在于它的功能性,STARTUP快速启动,DRAIN排空,PROBE_BW稳定发送,PROBE_RTT处理拥塞(排空+RTprop重新测量)。

bbr的收敛性

谈TCP BBR拥塞控制算法_第3张图片
当带宽增加一倍时,因为bbr的PROBE_BW阶段会周期性的尝试探测更多带宽,每个周期为8个往返时间,每个周期增长1 / 4,所以,如果带宽从10Mb增长到20Mb,那么需要约3个周期,使带宽收敛至增长后的带宽大小。可以看到,20s时,因为带宽的增长使连接探测到更大的带宽,所以之后的几个RTT内,BW的增长使inflight不断的膨胀,最终在约3个周期后达到最大带宽收敛。

当带宽减小一半时,因为带宽的计算使用一段滑动窗口时间内最大值的原因,bbr使用的带宽值并没有直接减小,所以在40s时,因为发送速率过大缓冲区膨胀,造成inflight和rtt激增。当滑动窗口移动,带宽缩减后的带宽测量值成为计算值之后,重新计算的cwnd小于inflight,这才使网络流量被排空,网络逐渐收敛。

bbr的公平性

谈TCP BBR拥塞控制算法_第4张图片
因为PROBE_BW状态增益系数的存在,会使得大流不断出让带宽给小流,最终达到一个公平状态。

同时,因为新流的加入,会使得网络队列开始被填充,这将造成已有连接在一段时间内都无法测量到最小RTT,从而进入PROBE_RTT状态。在这个状态中,cwnd会被设置为4个MSS,这将使得网络被排空,而已有大流连接排空的资源,将会被新流共享并最终收敛,这就是bbr的公平性。

参考资料

[1]Neal Cardwell, Yuchung Cheng, C. Stephen Gunn, Soheil Hassas Yeganeh, Van Jacobson.BBR: Congestion-Based Congestion Control.
[2]dog250.来自Google的TCP BBR拥塞控制算法解析.https://blog.csdn.net/dog250/article/details/52830576.
[3]dog250.Google’s BBR TCP拥塞控制算法的四个变速引擎.https://blog.csdn.net/dog250/article/details/52879298

你可能感兴趣的:(传输层)