TCP 拥塞避免算法( 九 )


总之说 BBR 处理丢包的时候需要区分 RTO 和 Fast Retransmission 两个场景 , RTO 下与 CUBIC 差不多;只有 Fast Retransmission 下 , 发送速率还能保持在较高位置 , 但也是受影响的 。
下面是 CUBIC (红色)和 BRR (绿色)在面对丢包的时候吞吐量表现 。CUBIC 在丢包 1% 的时候基本就无法工作了 , BRR 能扛到 20% 的丢包率 。黑线是理想状况下的吞吐量 , 因为有丢包存在 , 所以吞吐量随着丢包率升高而递减 。

TCP 拥塞避免算法

文章插图
 
来自[4]
对于右侧绿线是个断崖式有这么一些原因:
  • 丢包率高了以后一个是会引起 Fast Retransmission , 会对吞吐量有影响 , 另一个是可能出现 RTO , 出现 RTO 后 CWND 立即降到 1 跟 CUBIC 表现就一致了 , 吞吐量会大幅度下滑;
  • 丢包率高了之后会严重影响实际 Delivery Rate 的计算 , 让计算得到的值比实际值小 , 进而让 BBR 错误估计当前 BtlBw , 减小发送速率 。因为丢包率固定不变 , 减小发送速率后 Delivery Rate 可能会进一步减小 , 最终降为 0;
  • 最后 , 这个图本身就是指数的 , 即使是理想状态也会是个断崖;
对于为什么是丢包率接近 ProbeBW 增周期增益 (1.25) 时会出现吞吐量大幅度下滑我理解是这样的:
在估计 BtlBw 时是取过去一段时间内的最大值 , 比如丢包率是 10% , 如果没有增周期发送者通过 Delivery Rate 计算得到的带宽比实际 BtlBw 会低 10% , 之后会调整发送速度变成 90% BtlBw , 因为依然有 10% 的丢包率 , 在 90% BtlBw 从估计带宽用的滑动窗口过期移除后 , 发送速率会降为 90% * 90% BtlBw = 81% BtlBw  , 最终这么一步步下降到 0 , 这是没有增周期的场景 。
但是因为有增周期的存在 , 假设当前估算的带宽为 BtlBw , 普通周期发送速率就是 BtlBw , 增周期是 1.25 BtlBw , 减周期是 0.75 BtlBw 。当丢包率是 10% , 普通周期时计算出来的 Delivery Rate 是 90% BtlBw , 增周期计算出来的是 1.25 * 90% * BtlBw = 1.125 BtlBw  , 但实际上 BtlBw 是链路带宽不可能超越 BtlBw , 所以增周期 Delivery Rate 还是 BtlBw , 减周期是 0.75 * 90% * BtlBw = 0.675 BtlBw  , 这么一来根据过去一段时间 Delivery Rate 最大值估算带宽时得到的带宽还是 BtlBw , 所以 10% 丢包率的时候吞吐量受丢包的影响不大 。
当丢包率增长到 20% 的时候 , 根据上面的算法 , 增周期计算出来的 Delivery Rate 就马马虎虎刚好是 1 倍 BtlBw 了 , 因为 1.25 * 80% * BtlBw = 1 BtlBw。只要有风吹草动让计算的 Delivery Rate 低于最初的 BtlBw , 那一步步的计算的 Delivery Rate 就会和实际带宽偏离越来越大 , 最终降到 0 。也就是说增周期的增益和丢包率的乘积能大于 1 , 就能保持发送速度 , 小于 1 则会断崖式下滑 , 大于 1 是不可能的 。
所以 BBR 对 CUBIC 在丢包方面的优势是说 , CUBIC 是算法结构上导致丢包一定会让性能大幅度下滑 。而 BBR 是在一定程度上能通过配置去容忍丢包 。比如增周期增益提升到 1.5 , 抗丢包能力一定会大幅度提升 , 但性能受重传数据影响会越来越大 。
采样的时候如果应用层没数据发送怎么办BBR 数据都是基于采样的 , 比如 ProbeBW 时候要按照 1.25 倍速率发数据 , 如果应用层没有那么多数据要发怎么办?
BBR 采样时候会标记数据是不是 app limited 。如果是因为 app 原因导致没有足够数据可发从而让 deliveryRate 降低了 , 收到 ACK 的时候如果这个 deliveryRate 没有高于现在估计的 BtlBw 最大值 , 则会丢弃这个 deliveryRate 不放入 BtlBw max filter 。高于当前 BtlBw 最大值能放入 max filter 的原因是链路上的实际 BtlBw 是个 Hard Limit , 不管怎样都不可能超过 , 所以如果 app limited 状态下 deliveryRate 都高于当前估算的 BtlBw , 则说明估计值太小了 。
既然 BtlBw max filter 是直接取采样得到的 deliveryRate 的最大值 , 那 app limited 时候即使测得的 deliveryRate 不高于现在 BtlBw 也直接放入 max filter 不就好了 , 反正因为它小也不会被取到?
目前来看虽然理论上说每次 BBR 都取的是 deliveryRate 的最大值就行了 , 就是 BtlBw , 但实际上 BtlBw max filter 并不是简单的取最大值就完了 , 里面还有点基于时间的函数对窗口期内的所有 deliveryRate 做了一些计算才得到的 BtlBw 。可以看参考 [2] 。所以 app limited 的值如果没有超过 BtlBw 则直接丢弃 。


推荐阅读