必须同时设置net.ipv4.tcp_congestion_control=bbr和net.core.default_qdisc=fq,内核≥4.9;临时用sysctl -w,永久写/etc/sysctl.conf并执行sysctl -p;验证需检查算法、可用列表、队列规则及ss -i输出含bbr或pacing。

直接改 net.ipv4.tcp_congestion_control 就能切换算法,但只设这一项大概率失效——BBR 必须配 net.core.default_qdisc=fq,CUBIC 或 Reno 则不需要,漏掉会降级或不生效。
怎么确认当前生效的拥塞算法
运行 sysctl net.ipv4.tcp_congestion_control,输出必须是 bbr、cubic 或 reno 等具体名称,不能是空或报错。如果返回 net.ipv4.tcp_congestion_control = cubic 却想用 BBR,说明配置没生效。
- 检查内核版本:
uname -r输出主版本号必须 ≥ 4.9;3.x 或 4.4.x 内核即使写入参数也无效 - 验证模块是否可用:
lsmod | grep tcp_bbr—— 返回空不等于不支持,但若modprobe tcp_bbr报Module not found,说明内核未编译该模块 - 查看实际连接是否使用目标算法:
ss -i sport = :80(替换为实际端口),输出中含ca: bbr才算真正生效
为什么只改 tcp_congestion_control 不够
BBR 的核心机制依赖精确发包节奏(pacing),而 pacing 需要底层队列调度器支持。Linux 默认的 pfifo_fast 队列不支持 pacing,会导致 BBR 退化成类似 CUBIC 的行为,吞吐震荡、延迟不稳。
- 必须同步设置:
net.core.default_qdisc=fq(FQ 是唯一被内核官方推荐与 BBR 搭配的队列规则) - 验证队列是否生效:
tc qdisc show dev eth0(把eth0替换为实际网卡名),输出应含fq,而非pfifo_fast或cake - CUBIC/Reno 不强制要求 FQ,但设成
fq也无害;若用cake或pie,BBR 可能部分失效,不建议混用
临时 vs 永久配置的区别和风险
临时命令适合验证兼容性,永久配置才影响重启后行为。两者参数一致,但加载时机和持久性不同。
- 临时启用(立即生效,重启丢失):
sudo sysctl -w net.core.default_qdisc=fqsudo sysctl -w net.ipv4.tcp_congestion_control=bbr - 永久启用(写入配置文件):
向/etc/sysctl.conf追加两行:net.core.default_qdisc=fqnet.ipv4.tcp_congestion_control=bbr
再执行sudo sysctl -p加载 - 常见坑:
sysctl -p报错“Invalid argument”通常是因为某行末尾多了空格或用了中文标点;用sysctl --system可同时加载/etc/sysctl.d/*.conf,更健壮
客户端和服务端必须双向启用才有效
BBR 效果取决于整条路径上的两端:仅服务端启用,客户端仍用 CUBIC,发送节奏不匹配,优势几乎归零;反之亦然。尤其注意云厂商 SLB、CDN 节点、企业防火墙等中间设备,它们可能重置 TCP 选项或丢弃 pacing 包。
- Nginx/Apache 等服务端启用 BBR,只取决于其运行环境的内核配置,跟软件本身无关
- 客户端如 curl、wget 默认继承系统设置;浏览器(Chrome/Firefox)在 Linux 上也走内核 TCP 栈,但 Windows/macOS 客户端需单独调优
- 实测时用
iperf3 -c server_ip -A(-A关闭自动调优)比单纯测网页加载更能暴露算法差异
最常被忽略的是中间网络设备对 pacing 包的兼容性——有些老旧企业防火墙或运营商 NAT 设备会静默丢弃带 pacing 时间戳的 TCP 包,导致连接回退到 CUBIC,此时 ss -i 显示仍是 ca: bbr,但实际行为已降级。真要排查,得抓包看 TCP Option 中是否有 0x05(TS-ECR)和 pacing 相关字段。











