BBR 拥塞控制算法深度解析
BBR(Bottleneck Bandwidth and Round-trip propagation time)由 Google 的 Neal Cardwell、Yuchung Cheng 等人开发,是目前最先进的基于模型的拥塞控制算法之一。与传统的基于丢包的算法(如 Reno、CUBIC)不同,BBR 通过直接测量网络的瓶颈带宽和传播延迟来建模网络路径,在瓶颈点以 BDP(带宽延迟积)速率发送数据。
BBR 的核心思想是:丢包不等同于拥塞。在深缓冲区(Bufferbloat)或无线链路上,丢包可能由信道噪声或缓冲区过度排队引起,而非真正的链路饱和。BBR 通过主动测量带宽和延迟来精确控制发送速率,而非被动地等待丢包信号。
BBR 的核心模型
BBR 基于两个关键测量值构建网络模型:
flowchart LR
subgraph 网络测量
BW["BtlBw<br/>瓶颈带宽<br/>最大交付速率"]
RTT["RTprop<br/>传播延迟<br/>最小 RTT"]
end
BW --> BDP["BDP = BtlBw × RTprop<br/>带宽延迟积"]
BDP --> OP["运行目标<br/>inflight ≈ BDP"]
BDP --> RATE["发送速率<br/>pacing_rate = BtlBw × gain"]
style BW fill:#4CAF50,color:#fff
style RTT fill:#2196F3,color:#fff- BtlBw(瓶颈带宽):链路的最大交付速率,通过测量一段时间内的最大交付带宽获得。它代表了路径上最窄链路的数据传输能力上限。
- RTprop(传播延迟):链路的最小往返时间,通过测量一段时间内的最小 RTT 获得。它代表了信号在物理介质上传播所需的最短时间,不包括排队延迟。
- BDP(Bandwidth-Delay Product):BtlBw × RTprop 的乘积,描述了"管道"中可以容纳的最大数据量。
BBR 的核心目标是在瓶颈点维持恰好 BDP 的数据量——数据太多会在缓冲区排队(增加延迟),数据太少则无法充分利用带宽。这个平衡点被称为"最优运行点"(Optimal Operating Point)。
BBR 的测量机制
BBR 区别于传统拥塞控制算法的核心在于其测量机制。它不是通过丢包信号来推断拥塞,而是通过主动测量网络路径的两个固有属性:瓶颈带宽(BtlBw)和传播延迟(RTprop)。
BtlBw 测量:最大值滤波器
BtlBw 的测量基于一个关键观察:当发送端的数据管道被填满时,ACK 返回的速率等于瓶颈链路的服务速率。BBR 在每个 RTT 周期结束时计算交付速率(Delivery Rate):
| |
这个值需要经过一个最大值滤波器(Windowed Max Filter),典型窗口为 10 个 RTT。窗口化最大值滤波器的设计原因如下:
- 消除测量噪声:单次交付速率可能受到 ACK 压缩、接收窗口限制等因素影响
- 跟踪带宽变化:10 个 RTT 的窗口既能快速响应实际带宽增长,又能过滤短暂波动
- 保守递增:最大值滤波器确保 BtlBw 估计值只增不减,直到窗口过期后重新测量
当一个窗口周期(10 RTT)内没有出现更高的 delivery_rate 时,BBR 会降低 BtlBw 的估计值,以响应瓶颈带宽的实际下降。
RTprop 测量:最小值滤波器
RTprop 的测量利用了 TCP 的 ACK 时间戳特性。每次收到 ACK 时,BBR 计算该数据包的 RTT:
| |
这个值需要经过一个最小值滤波器(Windowed Min Filter),典型窗口为 10 秒。窗口化最小值滤波器的设计原因如下:
- 过滤排队延迟:只有当缓冲区完全排空时,测得的 RTT 才等于真实的传播延迟。最小值滤波器自动选择这些"干净"的样本
- 适应路由变化:10 秒的窗口足够长以捕获队列排空的机会,又足够短以响应 IP 路由变化引起的路径延迟变化
- 对噪声具有鲁棒性:延迟噪声(调度延迟、中断处理)只会增加 RTT,不会被最小值滤波器选中
flowchart TD
subgraph BtlBw 测量
BW1["发送数据<br/>填满管道"] --> BW2["收到 ACK<br/>计算交付速率"]
BW2 --> BW3["最大值滤波器<br/>10 RTT 窗口"]
BW3 --> BW4["BtlBw 估计值"]
end
subgraph RTprop 测量
RT1["发送数据<br/>记录时间戳"] --> RT2["收到 ACK<br/>计算 RTT"]
RT2 --> RT3["最小值滤波器<br/>10 秒窗口"]
RT3 --> RT4["RTprop 估计值"]
end
BW4 --> OP["最优运行点<br/>BDP = BtlBw × RTprop"]
RT4 --> OP
style BW4 fill:#4CAF50,color:#fff
style RT4 fill:#2196F3,color:#fff
style OP fill:#FF9800,color:#fff为什么使用窗口滤波器?
网络状态是动态变化的。使用窗口滤波器而非全局的 max/min 是为了在测量精度和适应性之间取得平衡:
- 无限期的最大值滤波器会使 BtlBw 永远停留在历史最高值,无法响应带宽下降
- 无限期的最小值滤波器会使 RTprop 永远停留在历史最低值,无法响应路由变化
- 窗口长度是经验总结:10 RTT 对带宽变化的响应足够快,10 秒对延迟变化的响应足够及时
BBR 的四状态机
BBR 通过四个状态的循环来探测和维持最优运行点:
flowchart TD
STARTUP["STARTUP<br/>增益 2.77<br/>指数探测带宽上限"]
DRAIN["DRAIN<br/>增益 0.35<br/>排空启动队列"]
PROBE_BW["PROBE_BW<br/>增益循环 1.25/0.75/1<br/>周期性探测带宽"]
PROBE_RTT["PROBE_RTT<br/>增益 0.75<br/>排空队列<br/>重新测量 RTprop"]
STARTUP -->|"发现带宽增长放缓<br/>或检测到丢包"| DRAIN
DRAIN -->|"inflight ≤ BDP"| PROBE_BW
PROBE_BW -->|"距上次 PROBE_RTT > 10s"| PROBE_RTT
PROBE_RTT -->|"RTprop 更新<br/>或持续 200ms"| PROBE_BW
style STARTUP fill:#f44336,color:#fff
style DRAIN fill:#FF9800,color:#fff
style PROBE_BW fill:#4CAF50,color:#fff
style PROBE_RTT fill:#2196F3,color:#fffSTARTUP 阶段
BBR 以指数方式探测瓶颈带宽上限,类似传统拥塞控制的慢启动阶段。每个 RTT 将发送速率加倍(增益 ≈ 2.77,因为需要同时填满管道和产生探测效果)。STARTUP 阶段的详细行为:
- 增益设定为 2.77,相当于每个 RTT 将发送量提高约 177%
- 持续监测带宽增长速率,当**连续三个 RTT 中带宽增长都低于 25%**时,判定已经接近瓶颈带宽上限
- 如果检测到丢包,也立即退出 STARTUP
- 退出 STARTUP 时,记录当前带宽估计值为 BtlBw
DRAIN 阶段
STARTUP 阶段指数级增长的数据量不可避免地会在缓冲区中产生队列。DRAIN 阶段的目的是排空这些队列:
- 增益设为 0.35,大幅降低发送速率
- 持续观察 inflight 数据量,直到其回落到 BDP 水平
- 队列排空后,路径上的排队延迟消失,此时测得的 RTT 才是真正的 RTprop
PROBE_BW 阶段
这是 BBR 的稳态阶段,占运行时间的 99% 以上。通过周期性的增益循环持续探测可用带宽的微小变化。
PROBE_RTT 阶段
如果距离上次 PROBE_RTT 已经超过 10 秒,BBR 会暂时降低发送速率以确保队列排空,获得准确的 RTprop 测量值。
PROBE_BW 增益循环
PROBE_BW 阶段采用 8 个相位的固定增益循环来持续探测网络状态:
flowchart LR
P1["增益 1.0<br/>稳定发送"] --> P2["增益 1.0<br/>稳定发送"]
P2 --> P3["增益 1.0<br/>稳定发送"]
P3 --> P4["增益 1.25<br/>↑ 探测带宽上限"]
P4 --> P5["增益 0.75<br/>↓ 排空队列"]
P5 --> P6["增益 1.0<br/>稳定发送"]
P6 --> P7["增益 1.0<br/>稳定发送"]
P7 --> P8["增益 1.0<br/>稳定发送"]
P8 --> P1
style P4 fill:#f44336,color:#fff
style P5 fill:#2196F3,color:#fff为什么 1.25 和 0.75?
增益值的设计基于排队理论的精确计算:
1.25 增益(探测相位):发送速率临时超过瓶颈带宽 25%,在瓶颈处产生一个小队列。这 25% 的超额发送量足以在一两个 RTT 内填满部分缓冲区,让发送端观察到交付速率的上限。如果探测成功(没有导致丢包),BBR 就确认当前的 BtlBw 仍然有效;如果探测到更大的交付速率,则更新 BtlBw 估计值。
0.75 增益(排空相位):将发送速率降低到瓶颈带宽的 75%,让瓶颈处的队列以 25% 的速率被排空。选择 0.75 而不是更低的值的理由是:
- 过低的增益会导致带宽利用率的显著下降
- 0.75 足以在下一个探测相位开始前排空队列
- 队列排空时间 ≈ (超额发送量) / (bottleneck_rate × 0.25),通常在一两个 RTT 内完成
1.0 增益(稳态相位):剩下的 6 个相位维持精确的 BDP 发送速率,不产生队列也不浪费带宽。这 6 个相位占据了循环的大部分时间,确保了整体带宽利用率接近 100%。
整个循环的数学期望增益正好是 1.0,意味着长期来看 BBR 不会在瓶颈处产生持续性的队列积累。
BBR v1 vs v2 vs v3
BBR 自 2016 年发布以来经历了三次重大迭代,下表对比了各版本的关键差异:
| 特性 | BBR v1 (2016) | BBR v2 (2019) | BBR v3 (2023) |
|---|---|---|---|
| 拥塞信号 | 仅带宽+延迟 | 带宽+延迟+ECN+丢包 | 带宽+延迟+ECN+丢包 |
| 丢包容忍度 | ~15% | ~15% | ~15% |
| ECN 支持 | ❌ | ✅ | ✅ |
| Reno/CUBIC 共存公平性 | 较差 | 明显改善 | 良好 |
| STARTUP 窗口增益 | 2.89 | 2.89 | 2.77 |
| STARTUP 节奏增益 | 2.89 | 2.89 | 2.77 |
| 带宽收敛问题 | 存在 | 部分修复 | 完全修复 |
| PROBE_RTT 策略 | inflight=4(固定) | inflight=4(固定) | 动态调整 |
| 拥塞检测触发 | 8 个丢包事件/RTT | 8 个丢包事件/RTT | 6 个丢包事件/RTT |
| 多流公平性 | 欠佳 | 较好 | 优秀 |
BBR v3 的主要改进
BBR v3 是迄今为止最成熟的版本,主要改进包括:
- 带宽收敛修复:解决了在多流共享瓶颈时带宽估计不稳定的问题。v1 和 v2 中,增益循环可能导致多流竞争时带宽分配剧烈波动,v3 通过改进增益相位同步机制实现了平滑收敛。
- STARTUP 增益调整:从 2.89 降至 2.77,减少启动阶段在瓶颈处产生的排队深度和丢包概率。
- 更激进的拥塞检测:每个 RTT 内触发 STARTUP 退出的丢包事件阈值从 8 个降至 6 个,更早地对拥塞做出响应。
- 动态 PROBE_RTT:不再固定将 inflight 降到 4 个数据段,而是根据当前 RTT 与 RTprop 的偏差动态调整探测量,减少不必要的吞吐波动。
- 性能调优:整体降低了排队延迟和丢包率,在标准测试中延迟降低约 20%。
在 Linux 中启用 BBR
BBR 从 Linux 4.9 内核开始被集成进主线。以下是在 Linux 系统上启用 BBR 的完整步骤:
检查内核支持
| |
临时启用
| |
永久配置
| |
验证生效
| |
为什么需要 fq(Fair Queuing)?
BBR 依赖精确的 pacing(速率整形)来控制发送速率。fq 队列管理算法提供:
- 每流 pacing:自动为每个 TCP 流提供精确的速率控制
- 公平带宽分配:在多个流之间公平分配带宽
- 减少 burst:平滑数据发送,减少突发流量对瓶颈缓冲区的影响
如果使用 pfifo_fast 或其他无 pacing 支持的 qdisc,BBR 的精度会显著下降。
BBR 与 QUIC
QUIC(Quick UDP Internet Connections)协议由 Google 设计,现已成为 HTTP/3 的传输层基础。BBR 在 QUIC 的拥塞控制中扮演着核心角色。
QUIC 为何选择 BBR
QUIC 选择 BBR 作为默认拥塞控制算法的原因:
- 基于模型的优势:QUIC 运行在 UDP 之上,操作系统内核不提供 QUIC 的拥塞控制。BBR 基于模型而非丢包,不依赖内核的丢包检测机制(如重复 ACK 计数),更容易在用户态精确实现。
- 更好的移动网络表现:移动网络频繁发生切换(WiFi ↔ 蜂窝)、信号波动等问题,导致大量非拥塞丢包。BBR 不依赖丢包信号,在这些场景下表现远优于 CUBIC。
- 低延迟要求:QUIC 承载的 HTTP/3 流量对首字节延迟敏感。BBR 的 PROBE_BW 稳态将排队延迟最小化,比 CUBIC 的窗口增长-丢包-减半循环更适合实时交互场景。
BBR 对 QUIC 连接迁移的支持
QUIC 的连接迁移(Connection Migration)是其在移动网络中的关键优势。当客户端切换网络(如从 WiFi 切换到蜂窝)时:
| |
BBR 在此场景中的优势:
- 快速重估:连接迁移后,新路径的 BtlBw 和 RTprop 完全不同。BBR 的 STARTUP 阶段可以在 1-2 个 RTT 内快速探测新路径的带宽上限
- 0-RTT 恢复:配合 QUIC 的 0-RTT 连接迁移机制,BBR 无需等待握手即可在新路径上发送数据
- 避免 CUBIC 的"冷启动"问题:CUBIC 在新路径上需要漫长时间的窗口探测过程,而 BBR 通过主动测量快速收敛
实际部署现状
目前 Google 的 QUIC 实现、Chromium 网络栈以及 Caddy、Nginx 等 Web 服务器的 QUIC 实现都默认使用 BBR。据 IETF 报告,互联网上超过 40% 的流量使用 BBR 或 BBR 衍生的拥塞控制算法。
BBR 在实践中的表现
适用场景
flowchart TD
subgraph 适用场景
WL["无线网络<br/>WiFi/4G/5G<br/>随机丢包 1-5%"]
LL["长肥网络<br/>高带宽 × 高延迟<br/>如海底光缆"]
BF["Bufferbloat<br/>深缓冲区<br/>排队延迟严重"]
RTI["实时交互<br/>视频会议/在线游戏<br/>对延迟敏感"]
end
subgraph 注意事项
F1["与 CUBIC 共存时<br/>可能抢占过多带宽<br/>需手动整形限速"]
F2["浅缓冲区<br/>增益循环导致<br/>周期性丢包"]
F3["短连接 (<10 RTT)<br/>BBR 尚未进入稳态<br/>优势无法发挥"]
F4["CPU 开销<br/>精确 pacing 和<br/>ACK 处理更复杂"]
end
WL --> B["BBR<br/>高性能 & 低延迟"]
LL --> B
BF --> B
RTI --> BBBR 在以下场景中表现尤为突出:
- 无线网络(WiFi/4G/5G):传统算法将随机无线丢包误判为拥塞,导致频繁降速。BBR 不受 1-5% 随机丢包影响,在信号不稳定的移动网络中维持高吞吐。
- 长肥网络:跨洋链路的高 BDP 使 CUBIC 的窗口增长极其缓慢。BBR 通过带宽主动探测快速收敛到最优值,无需漫长的 AIMD 过程。
- Bufferbloat 场景:深缓冲区下 CUBIC 会持续填满缓冲区导致数百毫秒排队延迟。BBR 的模型驱动方式在 BDP 点运行,避免了缓冲区过度占用。
- 实时交互应用:BBR 的低排队延迟特性对视频会议、云游戏等延迟敏感应用有显著改善。
使用注意事项
- 与 CUBIC 共存:BBR 倾向于抢占未使用带宽,与 CUBIC 流共存时可能获得不成比例的带宽。生产环境中建议对 BBR 流进行速率整形或使用公平队列调度。
- 浅缓冲区:BBR 的增益循环(1.25 → 0.75)在浅缓冲区中可能导致周期性丢包,影响短连接和小文件传输。可通过调整
tcp_bbr.*sysctl 参数缓解。 - 短连接:BBR 需要至少数个 RTT 来完成 STARTUP 和进入稳态。对于请求-响应模式的小文件传输(<10 RTT),BBR 的优势不明显,甚至可能因 STARTUP 的激进探测而增加延迟。
- CPU 开销:BBR 的 pacing 机制和 ACK 处理比 CUBIC 更复杂,在超高带宽(>100Gbps)下 CPU 开销不可忽视。
配置调优建议
对于需要精细化控制的生产环境,可以通过 sysctl 调整 BBR 行为:
| |
实际效果因网络条件而异,建议在目标环境中进行 A/B 测试后确定最优配置。
参考资料
- Cardwell, N., et al. (2016). BBR: Congestion-based congestion control. Communications of the ACM, 60(2), 58-66.
- Cardwell, N., et al. (2017). BBR: Congestion-based congestion control: measuring bottleneck bandwidth and round-trip propagation time. ACM Queue, 14(5).
- IETF Draft: BBR Congestion Control. https://datatracker.ietf.org/doc/draft-cardwell-iccrg-bbr-congestion-control/
- Google BBR GitHub Repository. https://github.com/google/bbr
- University of South Carolina. (2023). Evaluating TCP BBRv3 Performance in Wired Broadband Networks.
- Cheng, Y., et al. (2016). Delayed ACK and its impact on BBR. Google Technical Report.
- Linux Kernel BBR Documentation. https://www.kernel.org/doc/html/latest/networking/bbr.html
- QUIC IETF RFC 9000: Transport. https://datatracker.ietf.org/doc/rfc9000/