BBR 拥塞控制算法
BBR: Bottleneck Bandwidth and RTT
BBR 发明的目的是解决2个问题。
- 在有一定丢包率的网络链路上充分利用带宽
- 降低网络链路上的buffer占用率,降低延迟。
BBR 原理 使用极大带宽和极小延迟的乘积作为发送窗口大小。
其他拥塞算法原理
所有拥塞算法目标都是最大化利用网络上瓶颈链路的带宽,通常办法是不断增加数据量,直到发生丢包或者延迟增大等这些信号表明当前带宽已经使用100%。 GCC等其他算法都是基于某些信号认为网络发生拥塞,例如丢包。
网络链路上能容纳的数据量=链路带宽×往返时延 但是常用的标准TCP拥塞控制算法的问题在于:
- 网络上丢包不都是拥塞导致的,可能是传输错误导致的丢包,如果因为传输错误的丢包影响算法对带宽的评估,是失败的。
- 网络中的缓冲区buffer会被计算在内被占用,计算出的带宽=真实带宽+buffer大小, 问题称为buffrbloat (缓冲区膨胀)
缓冲区膨胀问题:
- 增加网络延迟, buffer东西越多,排队时间越长
- 共享网络瓶颈的连接较多时,可能导致缓冲区被填满而丢包,被误认为发生拥塞。 这个地方有点不理解
BBR和常规算法区别
- 既然区分不了拥塞丢包和错误丢包,就不考虑丢包这个信号
- 不断加快数据发送量,容易产生缓冲区膨胀,就单独估计带宽和延迟,而不是简单加快发送数据量。
BBR算法步骤
BBR分为3个阶段
- 慢启动:增加数据量,计算最大发送窗口
- 排空阶段:清空数据量,基本不发数据,计算最低延迟
- 稳定阶段:交替探测带宽和延迟
下图是发送速率(发送窗口)和时延与网络中的数据量关系
随着数据量增加,发送速率达到最高点100%即达到真实带宽,再继续增加数据量会占用buffer而不会增加发送率,RTT在发送率到达100%之前都是最小值,超过后开始产生延迟,且越来越高,直到buffer溢出发生丢包。
BBR会在窗口1和窗口2之间停下,会超过真实带宽单但没到丢包。 基于丢包的标准TCP会在窗口2停下,直到丢包才停止。
所以BBR需要计算的就是蓝色和绿色的转折点,分别代表最低延迟和最大发送窗口。
计算最大发送窗口(带宽探测)
刚开始时采用慢启动,每个包都会收到ACK,当发现通过i计算ACK得到的带宽 没有因为增加发送率而增加时,就知道此时已经占用了buffer,开始结束第一阶段,得到的值是3倍bandwight。
计算最低延迟(排空阶段)
因为要计算最低延迟,需要将inflight数据清空,发送极少数据才能保证RTT是极小值. 指数降低发送速率,buffer被慢慢排空,把上一个阶段占用的2倍bandwight的buffer消耗掉,直到延迟不再降低,则为最小延迟(因为buffer的存在说明有数据在排队,会增加延迟)。
稳定阶段
以8个往返为周期,第一个往返时间里,BBR增加为1.25倍的发包率,在第二个时间里,降低为0.85的发包率。后面6个往返里使用估计的带宽发包。 这里主要是带宽探测任务,
BBR每过10s ,如果最小延迟没有变化,就进入探测阶段,持续时间200ms, 发送窗口固定4个包,用来探测最小延迟作为新的延迟估计。大约2%的时间BBR用极低的发包率来测量延迟
性能评估
BBR对于带宽变化的响应
大部分时间内带宽的变化比延迟变化更频繁,BBR绝大多数时间都处于带宽探测阶段 *蓝色是延迟,绿色是inflight数量* 当带宽增长一倍时,BBR会每个周期向上探测1.25倍,大概3个周期后就能达到增长后的带宽。
当带宽降低一半时,多出来的包占用了buffer,导致延迟显著增加,但是延迟采用的是不发包测得的极小值,对于刚刚实际延迟增加没有影响。 带宽估计 是使用一段滑动窗口内的极大值,滑动窗口是多个往返周期,所以需要等当前任务滑出窗口后,发送窗口减半,估计带宽降低一半,发送包速率键盘,buffer被排空,延迟才会缓慢下降。
带宽增加一倍,BBR用时1.5s收敛; 带宽降低一半,BBR用时4s收敛;
BBR与标准TCP效果比对
BBR 要解决的第一个问题,丢包错误导致误判拥塞问题。
只要有0.01%丢包率,标准TCP带宽只剩下30%。 0.1%丢包率TCP带宽只有10%。1%丢包率几乎停滞。
而BBR在5%以下几乎没有带宽损失, 15%时仍然有75%带宽
BBR 要解决的第二个问题,降低延迟,减少缓冲区膨胀。 TCP倾向于填满缓冲区,延迟就越高,当用户网络接入速度很慢时,延迟可能超过造成连接失败。 BBR不会占用多于的缓冲区,会有单独的延迟探测阶段可以避免这个问题