BBR 与 CUBIC:跨地域传输变慢的一个常见原因
一个很典型的场景:两台机器各自测上行都正常,但从一端下载另一端的数据,速度只有十几 KB/s。换网页、换客户端都没用,ping 也通、丢包率看着也不高。这种时候,问题往往不在带宽,而在发送端选择的拥塞控制算法。
两种算法看待丢包的方式不同
CUBIC 是 Linux 长期默认的算法。它的基本假设是:丢包意味着拥塞。一旦检测到丢包,就把拥塞窗口砍下来,然后慢慢再涨回去。
BBR 不这样看。它持续测量两个量:瓶颈带宽(数据能跑多快)和往返时延(数据在路上要多久),然后按这两个量的乘积控制发送速率,把丢包当成信号噪声而不是拥塞证据。
差别在高时延链路上会被放大:往返 190 ms 时,CUBIC 靠丢包找上限,涨得慢、退得快;而链路上只要有千分之几的随机丢包(抖动、中间设备策略、无线段都可能有),它就会长期停在低窗口。
一组实测数字
同一台机器、同一个对端,只改拥塞控制算法:
| 算法 | 下载速度 | TLS 握手 |
|---|---|---|
| CUBIC | 约 18 KB/s | 2.6 s |
| BBR + fq | 1.4–2.1 MB/s | 0.66 s |
条件:往返时延约 190 ms,丢包率约 0.3%。带宽并没有变,变的只是发送端怎么决定发多快。
怎么改
先看当前值,确认内核支持:
sysctl net.ipv4.tcp_congestion_control
sysctl net.ipv4.tcp_available_congestion_control
如果列表里没有 bbr,说明内核模块没加载(多数发行版 4.9 以后都自带)。启用并持久化:
cat >> /etc/sysctl.d/90-bbr.conf <<'EOF'
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
EOF
sysctl --system
改完用 sysctl net.ipv4.tcp_congestion_control 复核,而不是只看文件写没写进去。
排查顺序(我实际用的)
- 先分方向:上传快、下载慢,或者反过来?只有一端慢,八成是发送端的问题,不是带宽。
- 再看差值:两个方向差十倍以上,先怀疑拥塞控制,别急着怪无线、怪运营商。
- 多次采样取中位数:晚高峰本来就慢,单次测速不能下结论。
- 改完再测同一组条件:否则你分不清是算法生效了还是网络自己好了。
一句话结论:跨地域传输慢,先比「上传 vs 下载」。差十倍以上就是发送端拥塞控制,不是带宽。