现代拥塞控制算法
经典算法的局限
RFC 5681 的 Reno 算法(慢启动 + 拥塞避免 + 快重传 + 快恢复)在以下场景表现不佳:
| 场景 | 问题 |
|---|---|
| 高带宽延迟积(BDP)网络 | 线性增长太慢,无法充分利用带宽 |
| 高丢包率网络(如 Wi-Fi/移动) | 丢包 ≠ 拥塞,窗口频繁减半 |
| RTT 差异大的连接共享瓶颈 | 短 RTT 连接增长更快,不公平 |
| 数据中心内部 | 延迟敏感,需要快速收敛 |
CUBIC(RFC 8312,Linux 默认)
CUBIC 是 Linux 内核默认的拥塞控制算法,使用三次函数替代线性增长:
cwnd = C × (t - K)^3 + W_max
其中:
- t = 距离上次丢包的时间
- W_max = 上次丢包前的 cwnd 值
- K = 从 W_max 降至 ssthresh 所需时间
- C = 常数(默认 0.4)
CUBIC 的特点:
- 远离 W_max 时激进增长:快速探测可用带宽
- 接近 W_max 时保守增长:避免再次触发拥塞
- RTT 公平性:窗口增长仅依赖两次拥塞事件之间的时间差,而非 RTT,对 RTT 差异大的连接更公平
- 高 BDP 友好:在卫星链路等长肥管道中表现优异
BBR(Bottleneck Bandwidth and RTT,Google)
BBR 彻底改变了拥塞控制的哲学:不依赖丢包作为拥塞信号,而是主动测量网络的两个核心参数:
BBR 的两个核心测量
BtlBw(瓶颈带宽):
- 测量方法:记录每个 RTT 内成功交付的数据量,取最大值
- 反映:链路物理带宽上限
RTprop(传播延迟):
- 测量方法:记录最小 RTT(排除排队延迟)
- 反映:光速限制下的理论最小延迟
BBR 的状态机
BBR 的优势
| 场景 | Reno/CUBIC | BBR |
|---|---|---|
| 高丢包率(1%) | 吞吐急剧下降 | 几乎不受影响 |
| Wi-Fi/移动网络 | 丢包误判为拥塞 | 丢包 ≠ 拥塞 |
| 多条连接共享瓶颈 | 公平但效率低 | 更公平且高效 |
| 缓冲膨胀(Bufferbloat) | 加剧排队延迟 | 主动控制 inflight ≤ BDP |
BBR 的局限:
- 与丢包-based 算法共存时可能过于激进(抢占更多带宽)
- 对 ACK 聚合(ACK Compression)敏感
- 需要内核支持(Linux 4.9+)
算法对比总结
| 算法 | 拥塞信号 | 增长方式 | 适用场景 |
|---|---|---|---|
| Reno | 丢包 | AIMD | 传统网络,教学 |
| CUBIC | 丢包 | 三次函数 | 高 BDP,Linux 默认 |
| BBR | 主动测量 | 基于 BtlBw | 高丢包,无线,Bufferbloat |
| Vegas | RTT 增长 | 线性 | 低延迟,但公平性问题 |
数据中心 TCP(DCTCP)
数据中心内部网络特点:
- 高带宽(10~100Gbps)、低延迟(<100μs)
- 流量模式:大量短流(RPC)+ 少量长流(数据同步)
- 要求:低延迟、高吞吐、快速收敛
DCTCP(Data Center TCP):
- 利用 ECN 精确标记拥塞程度
- 根据 ECN 标记比例(而非二元丢包)调整 cwnd
- 窗口减少幅度与拥塞程度成正比
- 实现毫秒级收敛
本篇小结
- Reno 的 AIMD 在高 BDP/高丢包场景表现不佳
- CUBIC:三次函数增长,RTT 公平,Linux 默认
- BBR:主动测量 BtlBw 和 RTprop,不依赖丢包,高丢包场景优异
- BBR 状态机:Startup → Drain → ProbeBW ↔ ProbeRTT
- DCTCP:数据中心专用,利用 ECN 精确控制
- 算法选择取决于场景:通用选 CUBIC,高丢包选 BBR,数据中心选 DCTCP
动手实践
查看和切换拥塞控制算法:
# 查看当前算法 sysctl net.ipv4.tcp_congestion_control # 查看可用算法 sysctl net.ipv4.tcp_available_congestion_control # 临时切换为 BBR sudo sysctl net.ipv4.tcp_congestion_control=bbr # 永久生效(写入 /etc/sysctl.conf) echo "net.ipv4.tcp_congestion_control=bbr" | sudo tee -a /etc/sysctl.conf用 iperf3 对比不同算法:
# 服务端 iperf3 -s # 客户端测试 CUBIC iperf3 -c <server> -t 30 # 客户端测试 BBR(需服务端也支持) iperf3 -c <server> -t 30模拟高丢包环境:
sudo tc qdisc add dev eth0 root netem loss 1% # 对比 Reno/CUBIC/BBR 的吞吐量差异思考:BBR 与 CUBIC 共享瓶颈链路时,谁会获得更多带宽?为什么?