【转载】从零理解 TCP 拥塞控制:为什么 BBR 比 CUBIC 快

网络拥塞控制示意:发送速率与网络容量的关系
一、TCP 拥塞控制的问题背景
互联网上的数据传输依靠 TCP,而 TCP 有一个核心难题:发送方不知道网络当前的承载能力,它只能通过"感知"来估计——发快了会丢包,发慢了浪费带宽。
传统的拥塞控制算法(Reno、CUBIC)都基于一个假设:丢包 = 网络拥塞。逻辑是这样的:
- 慢启动:指数级增加发送速率
- 拥塞避免:线性增加
- 检测到丢包:速率砍半,重新探测
这个逻辑在互联网早期很有效。但现代网络有一个变化打破了它——缓冲区膨胀(Bufferbloat)。
二、CUBIC:基于丢包的拥塞控制
CUBIC 是 Linux 内核 2.6.19 以后的默认算法,也是目前大多数服务器在用的算法。它用一个三次函数来控制窗口增长,在丢包后快速恢复,适合高带宽长距离链路。

CUBIC 的拥塞窗口变化曲线
CUBIC 的问题在于:现代路由器和交换机为了减少丢包,设置了很大的缓冲区。发送方可以一直塞数据进去,直到缓冲区满了才丢包——这时缓冲区里已经积累了大量数据,产生了严重的延迟。这就是"缓冲区膨胀"。
典型场景:你家的 4G 下行跑满的同时,打游戏延迟从 20ms 飙到 300ms——带宽很高,但延迟很差,就是因为缓冲区被塞满了。
三、BBR 的核心思想
Google 在 2016 年提出 BBR(Bottleneck Bandwidth and Round-trip propagation time),它彻底换了一个思路:不以丢包作为拥塞信号,而是主动测量网络的真实带宽和最小 RTT,把发送速率控制在"刚好不填满缓冲区"的水平。
BBR 要估算两个量:
- BtlBw(瓶颈带宽):最近一段时间内测量到的最大传输速率
- RTprop(传播时延):最近一段时间内测量到的最小 RTT(没有排队延迟时的纯传播时延)
理想的发送速率 = BtlBw,理想的在途数据量(inflight)= BtlBw × RTprop(即 BDP,带宽时延积)。

BBR 与 CUBIC 的吞吐量和延迟对比测试结果
四、BBR 的四个阶段
| 阶段 | 目的 | pacing_gain |
|---|---|---|
| STARTUP | 快速探测带宽上限,类似慢启动 | 2/ln2 ≈ 2.88 |
| DRAIN | 排空 STARTUP 多填入缓冲区的数据 | ln2/2 ≈ 0.35 |
| PROBE_BW | 稳态运行,周期性探测带宽变化 | 在 1.25 和 0.75 之间循环 |
| PROBE_RTT | 定期降速以测量真实 RTprop | —(cwnd 降到 4) |
其中 PROBE_BW 是最重要的稳态阶段。BBR 每 8 个 RTT 循环一次:用 1 个 RTT 以 1.25× 速率探测更多带宽,用 1 个 RTT 以 0.75× 速率排队,剩余 6 个 RTT 以 1.0× 稳定运行。这个设计让 BBR 能持续感知带宽变化,同时不会长期过度占用缓冲区。
五、BBR v2 和 v3 改进了什么
BBR v1 有一个被批评的问题:在与 CUBIC 共存时,BBR 会占用更多带宽,对 CUBIC 流不公平。原因在于 CUBIC 会因丢包退缩,而 BBR 不在意丢包,继续维持发送速率。
BBR v2(2019)和 v3(2023)引入了对丢包信号的适度响应,同时保留了基于 BDP 的带宽估计核心,改善了公平性。Google 在其全球骨干网(B4)上大规模部署 BBRv2/v3 后,吞吐量提升显著,延迟更稳定。
TCP 拥塞控制原理与 BBR 详解视频讲解(B站)
六、实际应用建议
- Linux 5.15+ 已包含 BBRv2 相关补丁,5.18+ 更完整。直接升级内核是最省事的方式。
- 云服务器(AWS/GCP/阿里云)的网络虚拟化层本身已经做了很多优化,BBR 的效果因环境而异,高带宽长延迟链路(如跨大洲)效果最显著。
- 家用宽带:如果你的路由器支持 BBR(OpenWRT/Padavan),开启后对视频通话和游戏的延迟稳定性有明显改善。
- BBRv3 目前还在 IETF 草案阶段,有条件可以自编译最新内核体验。
原文作者:网络工程师小李 · 发布于知乎专栏 · 转载已获授权(CC BY-SA 4.0)· 本站仅做排版调整,未修改原文内容