Tcp 拥塞控制讨论


#1

Linux4.9 内核发布了, 包含了 Google 最新发明的 BBR 拥塞控制算法. 一经发布便吸引了大量的眼球. 于是我们这个眼球也不能免俗, 来凑凑热闹吧.

传统的 TCP 拥塞控制算法, 都是基于 “丢包” 进行的. 以丢包作为拥塞的信号. 其实有2个严重的问题

  1. 丢包并不总是拥塞导致的, 也有可能是 GFW 的随机丢包策略, 当然也有可能是链路传输错误导致的. 这时候发生丢包, 恰恰要做的是立刻重发, 增大发送频率, 而不是降低发送速度.
  2. 现代的路由器总是以 “不丢包” 转发为荣. 而 TCP 是一定要丢包才能工作的. TCP 已经和现代路由器不兼容了. 为了不丢包, 路由器的缓冲非常大. 经过十几跳到达目的地的国际长途环境下, 途中的缓冲数量是惊人的. 当发生丢包的时候, TCP 已经属于严重过发状态了. 每个TCP都处于竞争烂发状态, 导致多跳数环境下的带宽延迟始终无法降低. 不利于改善全球网络环境.

基于不要丢包! 这样的考虑, 诞生了新一代的不丢包拥塞控制算法, CDG 算法. 这个算法以延迟作为判断依据. 当延迟增大的时候, 说明拥塞了, 数据开始在路由器的缓冲中积累. 于是就降低发送窗口.

CDG 算法的问题是, 和基于丢包的算法不兼容, 只有大家全用 CDG, 才是最佳的, 只要有人不用 CDG 而是基于丢包… 那丢包的人就能竞争走所有的带宽. 因为 CDG 是不丢包的.

这个世界不可能一下子就切换所有的设备. 这条路子就和 ipv6 一样是行不通的. CDG 于是也仅仅只能在全部机器都你一家控制的数据中心有点用途了.

对 CDG 的进一步改良发生在了 Google . Google 开发了 BBR 算法, 同 CDG 一样, BBR 算法不以丢包作为拥塞控制信号, 但是和 CDG 算法不同的是, BBR 能和 cubic 和 reno 共存.

BBR 能做到这点, 算法却意外的简单.

我们知道通信领域一个久经考验的公式:

带宽=窗口/延迟 

反过来,

窗口=带宽*延迟

只要知道了带宽和延迟, 那窗口该多大不就是显而易见了吗? 根本就不用去 “猜” 窗口大小. 而是直接算出来. 所有其他的拥塞控制算法, 都是在 “猜” 窗口大小. 拥塞了就缩一下, 没拥塞了就涨. BBR 算法反其道而行, 不去猜窗口大小, 而是直接算. 延迟是可以测量的, 带宽是可以测量的, 把2个测量值相乘, 就是最佳窗口大小.

困难在于, 延迟和带宽属于不相容可观察量, 符合量子力学的测不准原理, 是无法同时测量的.

BBR 的做法是, 分开测量.