背景知识
BBR (Bottleneck Bandwidth and RTT) 是 Google 出品的 TCP 拥塞控制算法,BBR 目的是要尽量跑满带宽,并且尽量不要有排队的情况。BBR 可以起到单边加速 TCP 连接的效果。
BBR解决了两个问题:
- 一定丢包率的网络链路上充分利用带宽。非常适合高延迟,高带宽的网络链路。
- 降低网络链路上的 buffer 占用率,从而降低延迟。非常适合慢速接入网络的用户。
网络链路上的包比较少时,道路很通畅,这个阶段,对于一个 TCP 连接来说,它的速度由这个连接两端之间的距离决定,也可以说是由 RTT 决定。当发包速率变大,把道路基本上填满了之后,这个阶段,带宽的大小决定了这个连接的速度,这时两端之间可能就会有包要排队,延迟时间除了 RTT 还有排队时间。
cwnd
是普通的拥塞控制算法里最终要求得的一个值,用来控制发包速率。BBR 也要求到这个值,但是它不是最主要的控制发包速率的变量,主要的变量是 pacing_rate
。
这两个变量都由探测到的带宽值和 RTT 值得到,整个过程都围绕着这两个值。在 BBR 算法中,有四种状态,几种状态可能会有如下的转换:
1 | | |
另外还有一个重要变量,是在不同状态,不同阶段取的不同增益系数,比如有时需要多发包探测到最大瓶颈带宽,有时需要把发包量降下来探测较为准确的 RTT。
STARTUP
类似与普通拥塞控制里的慢启动,增益系数是 2ln2
,每一个来回都以这个系数增大发包速率,估测到带宽满了就进入 DRAIN
状态 —— 连续三个来回,测得的最大瓶颈带宽没有比上一轮增大 25% 以上,就算做带宽满了。
进入 DRAIN
状态,增益系数小于 1,也就降速了。一个包来回,把 STARTUP
状态中产生的队列“抽干”,怎么样测算到队列空了?发出去还没有 ACK 的包量 inflight
,与 BDP (带宽延迟积)进行比较,inflight < BDP
说明空了,道路不那么满了,如果 inflght > BDP
说明还不能到下一个状态,继续 DRAIN
。
PROBE_BW
是稳定状态,这时已经测出来一个最大瓶颈带宽,而且尽量不会产生排队现象。之后的每个来回,在 PROBE_BW
状态循环(除非要进入下面提到的 PROBE_RTT
状态),轮询下面这些增益系数,5/4, 3/4, 1, 1, 1, 1, 1, 1,如此,最大瓶颈带宽就会在其停止增长的地方上下徘徊。大部分时间都应该处于 PROBE_BW
状态。
前面三种状态,都可能进入 PROBE_RTT
状态。超过十秒没有估测到更小的 RTT 值,这时进入 PROBE_RTT
状态,把发包量降低,空出道路来比较准确得测一个 RTT 值,至少 200ms 或一个包的来回之后退出这个状态。检查带宽是否是满的,进入不同的状态:如果不满,进入 STARTUP
状态,如果满,进入 PROBE_BW
状态。
启用 BBR
先甩一下 Google BBR 项目地址: https://github.com/google/bbr
目前已有 BBR v2 Alpha/Preview 版本
前置条件
Linux 内核 4.9 版本以上,请使用以下命令查看内核
1 | # uname -sr |
如果你是 Centos 系统可参照 Centos 升级内核的正确姿势 ,升级内核
Linux 内核从 4.9 开始已经支持 BBR 算法
设置
- 执行以下命令,sysctl.conf 增加 BBR 配置
1
2
3echo "# google bbr" >> /etc/sysctl.conf
echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf - 保存生效
1
sysctl -p
- 验证
1
2
3
4
5[root@yunwei ~]# sysctl net.ipv4.tcp_available_congestion_control
net.ipv4.tcp_available_congestion_control = reno cubic bbr
[root@yunwei ~]# lsmod | grep bbr
tcp_bbr 20480 1