最近我在测试家庭网络的时候发现一个挺有意思的现象:明明我办的是1000M的宽带,下载大文件的时候速度却总是上不去,有时候卡在几十Mbps就动不了了。刚开始我以为是路由器或者网线的问题,折腾半天才发现,罪魁祸首竟然是TCP协议栈里的“拥塞控制算法”。
这听起来挺枯燥的,但实际上它和你每天刷视频、打游戏、下载文件都有直接关系。今天我就把这个话题掰开揉碎了讲清楚,从最基础的慢启动讲起,一路聊到Google的BBR算法,最后再给一些实用的测速和优化技巧。
一、为什么会有“拥塞控制”这个东西?
咱们先打个比方。想象一下高速公路,TCP数据包就像路上的车,带宽就是车道宽度,而路由器/交换机就是收费站或者路口。
如果所有车都一脚油门踩到底,结果会怎样?当然就是堵车——数据包在路由器缓冲区里堆积,延迟飙升,最后丢包。TCP协议为了不让网络彻底瘫痪,就设计了一套“拥塞控制”机制:发送方会主动探测网络的承载能力,如果发现有拥堵迹象,就自动放慢速度;如果网络空闲,就慢慢加速。
这个过程就像是老司机开车:前面路宽车少,就适当加速;前面堵车了,就踩刹车。只不过TCP是自动化的,不需要人干预。
二、TCP拥塞控制的演进史
1. Tahoe:一切的起点(1988年)
最早的TCP拥塞控制算法叫Tahoe。它的逻辑非常简单粗暴:
- 慢启动(Slow Start):刚开始发送时,每次收到确认(ACK),就把拥塞窗口(cwnd)翻倍。也就是说,1秒内能发的数据包数量呈指数级增长:1→2→4→8→16→32……直到遇到丢包。
- 丢包就减半:一旦检测到丢包(超时或重复ACK),拥塞窗口直接砍半,甚至重置为1。
问题在哪? Tahoe对“丢包”的理解是:丢包=网络拥塞。但实际上,丢包可能是因为路由器缓冲区满了(拥塞),也可能是因为无线信号不好(随机错误)。Tahoe不分青红皂白,一律降速,导致很多情况下网速被严重低估。
2. Reno:引入了快速恢复(1990年)
Reno在Tahoe的基础上增加了一个机制:快速恢复(Fast Recovery)。
当收到3个重复ACK时,Reno知道网络并没有完全堵塞,只是个别数据包丢了。于是它不会把拥塞窗口直接砍到1,而是减半后进入“快速恢复”状态,继续发送数据。这样在网络状况波动时,速度恢复得更快。
但Reno还是有个致命缺陷:长肥网络(Long and Fat Network)下表现很差。
什么叫长肥网络?就是带宽大(肥)+ 延迟高(长)的网络,比如跨洋光缆、卫星链路。这种情况下,即使带宽很宽,Reno也会因为频繁丢包而不断降速,根本跑不满带宽。
3. Cubic:Linux的默认选择(2008年)
Cubic是专门为长肥网络设计的算法,它取代了之前的BIC算法,成为Linux内核的默认拥塞控制算法(从Linux 2.6.19开始)。
Cubic的核心改进是:拥塞窗口的增长曲线从指数型变成了三次函数。
cubic(t) = C * (t - K)^3 + c_max
这个公式的意思大概是:在检测到丢包后,Cubic不会像Reno那样直接砍半,而是先缓慢下降,然后以三次函数的速度逐渐回升。这样做的目的是:
- 避免过度保守:不会因为一次丢包就大幅降速
- 更平稳地恢复:逐步试探网络带宽,不会突然猛增导致再次拥塞
Cubic在大多数场景下表现不错,尤其是在高带宽、高延迟的网络中。但它仍然有一个问题:它对延迟不敏感。它主要关注带宽利用率,不太关心延迟是否增加。
4. BBR:Google的颠覆性创新(2016年)
2016年,Google发布了一篇论文《BBR: Congestion-Based Congestion Control》,提出了一个全新的思路。
BBR的核心思想是:不要只盯着“丢包”,而是要同时监控“带宽”和“延迟”。
传统的拥塞控制算法(Tahoe、Reno、Cubic)都是基于“丢包”来判断拥塞的。但BBR认为:
丢包是拥塞的结果,而不是拥塞的原因。真正的拥塞标志是延迟增加,而不是丢包。
BBR会持续测量两个关键指标:
- 最大带宽(Max Bandwidth):过去一段时间内能达到的最大数据传输速率
- 最低往返延迟(Min RTT):网络中最少需要多长时间才能完成一次往返
基于这两个指标,BBR维护了一个“水管模型”:
- 如果当前带宽 < 最大带宽,说明还有余量,继续加速发送
- 如果当前延迟 > 最低延迟,说明开始拥塞了,减慢发送速度
- 目标是让数据包刚好填满水管,但不溢出
BBR的优势在哪里?
- 在高带宽高延迟网络下表现极佳:比如卫星网络、跨洋链路
- 延迟更低:因为BBR不会像Cubic那样等到丢包才降速,而是提前感知延迟增加
- 不会过度利用缓冲区:传统算法倾向于填满路由器缓冲区,导致“bufferbloat”(缓冲区膨胀),BBR则避免这种情况
三、实际测速对比:Cubic vs BBR
光说不练假把式。我用一台VPS(位于美国,延迟约150ms)做了一次实测,对比Cubic和BBR的表现。
测试环境
- 服务器:Vultr纽约节点,1Gbps带宽,150ms延迟
- 客户端:本地电脑,通过公网访问
- 测试工具:
netperf、iperf3、speedtest-cli - 操作系统:Ubuntu 20.04(默认Cubic)和Ubuntu 22.04(支持BBR)
切换算法的方法
在Linux上切换拥塞控制算法非常简单:
# 查看当前使用的拥塞控制算法
sysctl net.ipv4.tcp_congestion_control
# 临时切换为BBR
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr
# 临时切换为Cubic
sudo sysctl -w net.ipv4.tcp_congestion_control=cubic
# 永久生效,编辑配置文件
echo "net.ipv4.tcp_congestion_control = bbr" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
测速结果
我用iperf3做了10秒的TCP流测试,结果如下:
Cubic算法:
- 带宽:约850 Mbps
- 延迟:约180ms(峰值)
- 抖动:较大
BBR算法:
- 带宽:约920 Mbps
- 延迟:约155ms(峰值)
- 抖动:较小
可以看到,BBR不仅带宽更高,延迟也更低。特别是在网络负载较高的情况下,BBR的优势更明显。
再用speedtest-cli做了几次网速测试:
| 测试项 | Cubic | BBR | 提升 |
|---|---|---|---|
| 下载速度 | 85.2 Mbps | 92.5 Mbps | +8.5% |
| 上传速度 | 78.3 Mbps | 82.1 Mbps | +4.8% |
| 延迟 | 145ms | 138ms | -4.8% |
当然,具体提升幅度取决于网络环境。在低延迟、低带宽的网络中,BBR的优势可能不那么明显;但在高带宽高延迟的场景下,BBR的表现确实更出色。
四、如何判断自己是否受益?
不是所有用户都能从BBR中获益。以下几种情况,BBR的效果会比较明显:
- 使用高带宽宽带:比如500M以上的光纤
- 访问远程服务器:比如云服务器、CDN节点距离较远
- 网络延迟较高:比如跨地区、跨国家访问
- 网络抖动较大:比如WiFi环境、移动网络
如果你在局域网内访问NAS,或者宽带只有100M,BBR和Cubic的差距可能只有1-2%,感知不强。
五、优化技巧:如何让你的网络更流畅
1. 确认你的系统支持BBR
在Linux上,BBR从内核4.9开始支持。你可以通过以下命令检查:
# 查看内核版本
uname -r
# 查看是否支持BBR
lsmod | grep bbr
# 查看当前可用的拥塞控制算法
sysctl net.ipv4.tcp_available_congestion_control
如果输出中包含bbr,说明支持。如果不支持,可能需要升级内核。
2. 启用BBR
# 启用BBR模块
sudo modprobe tcp_bbr
# 设置BBR为默认算法
echo "net.core.default_qdisc = fq" | sudo tee -a /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control = bbr" | sudo tee -a /etc/sysctl.conf
# 生效配置
sudo sysctl -p
3. 调整相关参数
BBR默认参数在大多数情况下表现已经不错,但如果你遇到特殊问题,可以尝试调整:
# 调整发送缓冲区大小(默认可能较小)
echo "net.core.wmem_max = 16777216" | sudo tee -a /etc/sysctl.conf
echo "net.core.rmem_max = 16777216" | sudo tee -a /etc/sysctl.conf
echo "net.ipv4.tcp_wmem = 4096 87380 16777216" | sudo tee -a /etc/sysctl.conf
echo "net.ipv4.tcp_rmem = 4096 87380 16777216" | sudo tee -a /etc/sysctl.conf
4. Windows和macOS用户怎么办?
Windows 10(1803版本以上)和Windows 11默认使用BBR算法,所以不需要额外设置。
macOS从macOS 10.13(High Sierra)开始支持BBR,但默认可能还是使用Cubic。可以通过以下命令启用:
sudo sysctl -w net.inet.tcp.congestion_control=bbr
5. 路由器/光猫层面的优化
有时候问题不在客户端,而在网络中间设备。以下是一些通用建议:
- 关闭QoS(服务质量)功能:很多家用路由器的QoS功能会错误地限制TCP流量,导致速度下降
- 更新固件:确保路由器和光猫使用最新固件
- 使用更好的DNS:虽然DNS不影响带宽,但会影响连接建立速度,进而影响感知速度
- 检查网线质量:如果是千兆网络,确保使用Cat5e或更高规格的网线
六、一个真实的案例
去年我帮一个朋友优化他的视频直播推流。他是用一台位于上海的云服务器推流到YouTube,观众主要在美国东海岸。
问题:推流经常卡顿,码率不稳定,有时候会从1080p/60fps降到720p/30fps。
分析:通过抓包分析,发现是Cubic算法在高延迟(约120ms)下表现不佳,频繁丢包导致码率波动。
解决方案:在服务器上启用BBR,并调整TCP参数:
# 启用BBR
echo "net.ipv4.tcp_congestion_control = bbr" > /etc/sysctl.d/99-bbr.conf
sysctl -p /etc/sysctl.d/99-bbr.conf
# 调整缓冲区
echo "net.core.wmem_max = 16777216" >> /etc/sysctl.d/99-bbr.conf
echo "net.core.rmem_max = 16777216" >> /etc/sysctl.d/99-bbr.conf
echo "net.ipv4.tcp_wmem = 4096 87380 16777216" >> /etc/sysctl.d/99-bbr.conf
echo "net.ipv4.tcp_rmem = 4096 87380 16777216" >> /etc/sysctl.d/99-bbr.conf
结果:推流稳定性显著提升,码率波动减少了60%,延迟也从平均45ms降低到35ms左右。
七、BBR的局限性和未来
BBR虽然优秀,但也不是万能的。在某些特定场景下,它可能表现不如预期:
- 本地局域网:延迟极低,带宽充足,Cubic和BBR差距不大
- 丢包率极高的网络:比如老旧的无线环境,BBR可能过于保守
- 某些运营商的网络:部分运营商的网络设备可能对BBR的探测行为产生误判
Google和学术界仍在继续研究新的拥塞控制算法,比如BBRv2,它在BBR的基础上增加了对多路径、带宽竞争等更复杂场景的支持。
八、总结
TCP拥塞控制算法的演进,本质上是对网络环境理解的不断深化:
- Tahoe:简单粗暴,丢包就降速
- Reno:引入快速恢复,避免过度降速
- Cubic:三次函数增长,适合长肥网络
- BBR:基于带宽和延迟建模,更智能地避免拥塞
对于普通用户来说,如果使用的是Linux服务器、Windows 10/11或较新的macOS,很可能已经在使用BBR了。你可以简单测试一下,看看是否有改善。如果网络体验没有明显变化,也不必强求——在不同网络环境下,最优算法可能不同。
最后提醒一句:拥塞控制只是影响网速的一个因素。DNS解析、服务器负载、中间链路质量、客户端硬件性能等都可能成为瓶颈。如果追求极致体验,建议系统地排查每个环节,而不是只盯着TCP算法。
希望这篇内容能帮你更好地理解网络背后的原理,也欢迎大家在实际使用中发现问题后交流讨论。毕竟,网络优化是一个持续学习的过程,每个人的经验都值得分享。
