2.6 网络拥塞控制原理与实践
你可能听说过TCP上的一些术语,例如Cubic、Tahoe、Vegas、Reno、Westwood,以及最近流行的 BBR 等。这些都是 TCP 中使用的不同拥塞控制算法。
拥塞控制算法决定网络传输的效率。在本节,我们分析拥塞控制的原理,互联网不同时期拥塞控制算法设计,深入理解 BBR 算法如何在弱网环境下大幅提升网络传输效率。
2.6.1 网络拥塞控制原理
网络传输效率与 RTT 和 传输速率密切相关:RTT 低意味着数据传输延迟较短;传输速率越高意味着网络可以在单位时间内处理更多的数据。图 2-22 展示了两者的变化逻辑以及对网络传输效率的影响。
图 2-22 RTT 与传输速率变化对网络传输效率的影响
首先,解释图中的一些术语,它们的含义如下:
- RTprop (Round-Trip propagation time,两个节点之间最小时延):两个节点之间的最小时延,取决于物理距离,距离越长,时延越大。
- BtlBw(Bottleneck Bandwidth,瓶颈带宽):如果把网络链路想象成水管,RTprop 就是水管的长度,BtlBw 则是水管最窄处的直径。
- BDP(Bandwidth-Delay Product,带宽和延迟的乘积):它代表了网络上能够同时容纳的数据量(水管中有多少流动的水)。 BDP 的计算公式是:BDP = 带宽 × 延迟。其中,带宽以比特每秒(bps)为单位,延迟以秒为单位。
- inflight 数据:指已经发送出去但尚未收到确认的数据包。这些数据包仍在网络中传输,等待接收方的处理或确认。。
inflight 数据受 RTT 和传输速率的影响,分为三个区间:
- (0,BDP):称为应用受限区(app limited)。在这个区间内,inflight 数据量未占满瓶颈带宽。RTT 最小、传输速率最高。
- (BDP,BtlBwBuffSize):称为带宽受限区(bandwidth limited)。在这个区间内,inflight 数据量已达到链路瓶颈容量,但尚未超过瓶颈容量加缓冲区容量。此时,应用能发送的数据量主要受带宽限制。RTT 逐渐变大,传输速率到达上限。
- (BDP + BtlBwBuffSize,infinity):称为缓冲区受限区(buffer limited)。在这个区间内,实际发送速率已超过瓶颈容量加缓冲区容量,超出部分的数据会被丢弃,从而产生丢包。RTT 以及传输速率均达到上限。
根据图 2-22,可以看出,拥塞本质是 inflight 数据量持续向右侧偏离 BDP 线的行为,而拥塞控制就是控制 inflight 数据量在以上哪个区间内。很明显,当 inflight 数据量处于应用受限区和带宽受限区的边界时,传输速率接近瓶颈带宽,也没有丢包。
2.6.2 早期拥塞控制旨在收敛
早期互联网的拥塞控制以丢包为控制条件,控制逻辑如图 2-21 所示。发送方维护一个叫拥塞窗口的状态变量 cwnd,其值取决于网络拥塞的程度和所采用的拥塞控制算法。
当发送发开始发送数据时,首先是慢启动(Slow Start),也就是慢慢增大拥塞控制窗口。当出现丢包时,进行拥塞避免(Congestion Avoiance),也就是减小拥塞控制窗口。当丢包不再出现时,再次进入慢启动阶段,如此一直反复。
图 2-21 早期以丢包为条件的拥塞控制
以丢包为控制条件的机制适应了早期互联网的特征:低带宽和浅缓存队列。但随着移动互联网的快速发展,尤其是图片和音视频应用的普及,使网络负载大幅增加。同时摩尔定律也推动设备的廉价化和性能提升,当路由器和网关的缓存队列增加,链路变得更长更宽时,RTT 有可能因缓存队列增大而增大,丢包有可能是链路太长,并不总是因为网络拥塞。传统的以丢包为控制条件的拥塞控制算法就不再适用了。
2.6.3 现代拥塞控制旨在效能最大化
如果说初代的拥塞控制目标旨在收敛,防止互联网服务产生“拥塞崩溃”,那么这一次 BBR 的目标则旨在充分利用链路带宽、路由/网关设备的缓存队列,使网络效能最大化。
网络效能最大化的前提是找到网络传输中的最优点。图 2-22 中的两个黑色圆圈即代表网络传输的最优点:
- 上面的圆圈为 min RTT(延迟极小值),网络中路由/网关设备的 Buffer 未占满,没有任何丢包情况;
- 下面圆圈的为 max BW(带宽极大值),网络中路由/网关设备的 Buffer 被充分利用。
当网络传输处于最优点时:
- 数据包投递率 = BtlBW(瓶颈带宽),保证了瓶颈链路被 100% 利用;
- 在途数据包总数 = BDP(时延带宽积),保证未占用 Buffer。
然而,延迟极小值和带宽极大值互相悖论,无法同时测得。如图 2-24 所示,要测量最大带宽,就要把瓶颈链路填满,此时 Buffer 中有一定量的数据包,影响延迟指标。要测量最低延迟,就要保证 Buffer 为空,此时就无法测量最大带宽值。
图 2-24 无法同时得到 max BW 和 min RTT
2.6.4 BBR 的设计原理
BBR 的解题思路是不再考虑丢包作为拥塞的判断条件,而是交替测量带宽和延迟。它使用一段时间内的带宽最大值和延迟最小值来估计发包速率,控制稳定发包速度,尽量榨干带宽,却又不让数据在中间设备的缓存队列上累积:
- 为了榨干带宽,BBR 周期性地探测链路条件是否变好了,如果是,则加大发送速率;
- 为了不让数据在中间设备的缓存队列上累积,BBR 会周期性地探测链路的最小 RTT,并使用最小 RTT 计算发包速率。
BBR 的拥塞控制状态机是实现上述思路的基础。BBR 的状态机在任何时刻都处于以下四个状态之一:启动(STARTUP)、排空(DRAIN)、带宽探测(PROBE_BW)和时延探测(PROBE_RTT)。它们之间的关系如图 2-23 所示。
- 启动阶段(STARTUP):当连接建立时,BBR 采用传统拥塞控制算法慢启动方式,指数级增加发送速率,目的是尽可能快的探测到带宽极大值。当判断连续时间内发送速率不再增长时,说明已到达瓶颈带宽,此时状态切换至排空阶段。
- 排空阶段(DRAIN):该阶段指数级降低发送速率,相当于启动阶段的逆过程,目的是将多占的 Buffer 慢慢排空。
- 完成以上两个阶段后,BBR 进入带宽探测阶段(PROBE_ BW),BBR 大部分时间都在该状态运行。当 BBR 测量到带宽极大值和延迟极小值,并且网络中在途数据包 inflight[^3] 等于 BDP 时,便开始以一个稳定的匀速维护着网络状态,偶尔小幅提速探测是否有更大带宽,偶尔小幅降速公平的让出部分带宽。
- 时延探测阶段(Probe RTT):如果估计延迟不变(未测量到比上周期最小 RTT 更小值),就进入延迟探测阶段。该状态下,拥塞窗口 Cwnd 被设置为 4 个 MSS(Maximum Segment Size,最大报文长度),并对 RTT 重新测量,持续 200ms,超时后,根据网络带宽是否满载决定状态切换为启动阶段或带宽探测阶段。
图 2-23 BBR 状态转移关系
2.6.5 BBR 的应用
Linux 内核从 4.9 开始集成了 BBR 拥塞控制算法。此后,在绝大数的 Linux 发行版中,只要几个命令就能使用 BBR 提升网络传输效率。
- 首先,查询系统所支持的拥塞控制算法。
$ sysctl net.ipv4.tcp_available_congestion_control
net.ipv4.tcp_congestion_control = bbr cubic reno
上面返回的结果中,显示当前系统支持 bbr、cubic 和 reno 三种拥塞控制算法。
- 查询当前使用的拥塞控制算法。
$ sysctl net.ipv4.tcp_congestion_control
net.ipv4.tcp_congestion_control = cubic
绝大部分 Linux 系统默认的拥塞控制算法为 Cubic 算法。
- 指定拥塞控制算法为 bbr。
$ echo net.ipv4.tcp_congestion_control=bbr >> /etc/sysctl.conf && sysctl -p
网络拥塞控制是单向生效,也就是说作为下行方的服务端调整了,BBR 算法即可生效。
2.6.6 BBR 性能表现
接下来,我们使用 tc 工具模拟弱网环境,使用网络性能测试工具 iperf3 测试弱网环境下不同的拥塞控制算法的表现。
首先,在服务端设置 eth0 网络接口上的流量丢包率为 1%、延迟为 25ms。
$ tc qdisc add dev eth0 root netem loss 1% latency 25ms
接着,在服务端使用 iperf3 开启测试服务,以服务端模式运行,设置监控时间2秒,并指定端口为 8080。
$ iperf -s -p 8080 -i 1
在客户端节点使用 iperf3 以客户端模式运行,请求 10.0.1.188 服务端的 8080 端口。
$ iperf3 -c 10.0.1.188 -p 8080
测试结果如表 2-3 所示。可以看出,BBR 在轻微丢包的网络环境下表现尤为出色。
表 2-3 各拥塞控制算法在不同丢包率环境下的性能测试 表数据来源
网络吞吐 | 拥塞控制算法(服务端) | 延迟 | 丢包率 |
---|---|---|---|
2.35Gb/s | Cubic | <1ms | 0% |
195 Mb/s | Reno | <140ms | 0% |
147 Mb/s | Cubic | <140ms | 0% |
344 Mb/s | Westwood | <140ms | 0% |
340 Mb/s | BBR | <140ms | 0% |
1.13 Mb/s | Reno | <140ms | 1.5% |
1.23 Mb/s | Cubic | <140ms | 1.5% |
2.46 Mb/s | Westwood | <140ms | 1.5% |
160 Mb/s | BBR | <140ms | 1.5% |
0.65 Mb/s | Reno | <140ms | 3% |
0.78 Mb/s | Cubic | <140ms | 3% |
0.97 Mb/s | Westwood | <140ms | 3% |
132 Mb/s | BBR | <140ms | 3% |