TCP 拥塞避免算法( 四 )


之前基于丢包的拥塞算法实际上就是和链路 Buffer 一起配合控制 Inflights 数据量在 BDP 那条线后面与 BDP 线的距离 。以前内存很贵 , 可能只比 BDP 大一点 , 基于丢包的算法延迟就不会很高 , 可能比最优 RTT 高一点 。但后来 Buffer 越来越便宜 , 链路上 Buffer 就倾向于做的很大 , 此时基于丢包的拥塞算法就容易导致实际占用的 Buffer 很大 , 就容易出现 BufferBloat 。
为了达到最优点 , 发送速率必须达到 BltBw , 从而占满链路带宽 , 最高效的利用带宽;再有需要控制 Inflight 数据量不能超过链路的 BDP = BtlBw * RTprop  , 从而有最优的延迟 。发送速率可以超过 BltBw , 可以有队列暂时产生 , 但数据发送总量不能超 BDP , 从而让平均下来延迟还是能在最优点附近 。

TCP 拥塞避免算法

文章插图
 
来自[4]
TCP VegasVegas 就如上面说的理想中算法一样 , 它会监控 RTT , 在尝试增加发送速率时如果发现丢包或者 RTT 增加就降低发送速率 , 认为网络中出现拥塞 。但它有这些问题:
  • CWND 增长是线性的 , 跟 Reno 一样需要很久才能很好的利用网络传输速率;
  • 最致命的是它不能很好的跟基于丢包的 Congestion Avoidance 共存 , 因为这些算法是让队列处在 State 2 和 3 之间 , 即尽可能让队列排队 , 也相当于尽可能的增大延迟 , 但 Vegas 是尽可能不排队 , 一发现排队就立即降低发送速率 , 所以 Vegas 和其它基于丢包算法共存时会逐步被挤出去;
BBR估计 BtlBw 和 RTprop延续前面说的 , 要把发送速率调整到跟 BDP 差不多大是最优的 。因为网络环境会持续变化 , 所以需要持续监控 RTprop 和 BtlBw 的值 。
RTprop 是链路固有传输延迟 , 我们无法直接监控到它 , 我们只能通过监控数据包的 RTT 来间接的得到 RTprop 的趋近值 。RTT 和 RTprop 关系如下:
TCP 拥塞避免算法

文章插图
 
η 是其它因素导致的 noise 延迟 , 包括接收端延迟 ack 等原因导致的延迟 。因为 RTprop 是链路上的固有延迟 , 可以认为只有链路上选择的路径变化时候它才会变化 , 并认为它变化频率很低 , 变化间隔时间远大于 η 。η 一定是正数 , RTT 无论如何不可能低于 RTprop , 所以可以在一个时间窗口 Wr 内(一般是在几十秒到几分钟之间)监控最小的 RTT 的最小值 , 认为就是近似为 RTprop 。
TCP 拥塞避免算法

文章插图
 
BtlBw 也是靠 Ack 来监控 。每收到一个 Ack 一方面是知道数据延迟 RTT 是多少 , 再有送达的数据量是多少 。我们在一个短的时间窗口 deltaT 内通过 Ack 计算对面收到了多少数据 , 得到 deliveryRate = deltaT 时间内送达数据量 / deltaT  , 这个速率一定低于链路上瓶颈速率 , bottleneck rate 。因为我们计算 deliveryRate 时使用的数据送达量是精确值 , 是在 Ack 里数据接收方明确告诉我们的 。而我们为了做带宽计算等待的 deltaT 时间一定大于实际时间 , 所以 deltaT 时间内送达数据量 / deltaT 计算得到的 deliveryRate 一定小于等于真实 deliveryRate , 这个真实 deliveryRate 又一定小于等于链路物理 bottleneck rate 。所以:
TCP 拥塞避免算法

文章插图
 
这里时间窗口 Wb 一般是 10 个 RTT 。
RTprop 和 BtlBw 是两个独立的量 , RTprop 变化比如选择的链路变化时 , bottleneck 可能是一样的 BltBw 不变;BtlBw 变化时候选择的链路可能没有变化 , 比如一个无线网络改变了发送速率 , 链路不变但带宽变大了 。
从之前看过的下面这个图能知道 , RTprop 只能在 BDP 线左侧被观测到 , 即发送数据比较少 , inflight 数据量没有到 BDP 的时候;BtlBw 只能在 BDP 线右侧能被观察到 , 即 inflight 数据超过 BDP , 延迟开始增大时被观测到 。直观一点说就是链路上队列没排队时候 , 你知道链路延迟是多少 , 但不知道队列最大消费速度是多少 , 当队列开始出现排队后 , 你在发送端计算得到接收率不变了 , RTT 延迟也升高了 , 知道最大接收率是多少 , 但又不知道链路上实际延迟是多大了 , 因为多了数据排队的时间 。


推荐阅读