如何在香港服务器的Ubuntu 20.04中启用TCP BBR拥塞控制算法,降低跨境访问延迟?

凌晨 1:40,客服把电话转给了我:“华北和华东的用户访问我们香港源站,页面经常卡住,视频也缓冲得厉害,能看看吗?”
我远程打开监控,几个指标刺眼:
- 跨境连接 RTT(p95)在 55–80ms 摆动不算离谱,但 TTFB(p95)冲到了 600ms+。
- TCP 重传率在晚高峰能上 2–3%。
- 带宽并没跑满,10G 口只有 2–3G 流量,却像“堵车”。
经验告诉我:这很像 Cubic 在轻微丢包 + 中等 RTT 的跨境链路上“保守开车”了。于是我决定在这台 Ubuntu 20.04 的香港服务器上启用 TCP BBR,通过更好的拥塞控制和精准节拍(pacing)把跨境时延压下去。
环境与目标
目标:在 Ubuntu 20.04 LTS 上启用 TCP BBR(v1),降低跨境访问的 应用层延迟(TTFB、页面首屏、API 响应 p95),同时提升弱丢包场景下的 有效吞吐。
机房与硬件(实配)
| 项目 | 参数 |
|---|---|
| 机房 | 香港葵涌(双上联:CMI + HKT,BGP 汇接) |
| 服务器 | Supermicro 1U |
| CPU | Intel Xeon Silver 4310 ×1 |
| 内存 | 64GB DDR4 |
| 存储 | Samsung PM9A3 1.92TB NVMe |
| 网卡 | Intel X710 10GbE(上联 10G) |
| 操作系统 | Ubuntu 20.04.6 LTS(原生 5.4 内核) |
| 业务 | Nginx + Node.js,HTTP/2 为主,部分文件下载直连 |
备忘:Ubuntu 20.04 默认 5.4 内核已支持 BBR v1;BBR v2 未主线稳定,不追求。
基线数据(启用前)
我按惯例先打了基线,避免“玄学优化”。
1)跨境下载吞吐(iperf3)
客户端:北京云主机(电信 CN2)
服务端:香港源站(10G 口)
配置:iperf3 -c <HK_IP> -t 60 -P 8
| 指标 | 数值(Cubic) |
|---|---|
| 平均吞吐 | 190–220 Mbps |
| 重传率 | 1.5–2.2% |
| RTT(mtr 中位) | 48–55ms |
2)Web 端到端指标(30 分钟滚动)
| 指标 | p50 | p95 |
|---|---|---|
| TTFB(动态 API) | 210ms | 620ms |
| 首屏可交互(首屏图文) | 1.2s | 2.8s |
| 下载 100MB 文件 | 6.8s | 12.5s |
备注:带宽没打满,延迟型卡顿明显,怀疑拥塞窗口在丢包后恢复太慢。
BBR 原理一句话(够用版)
Cubic 侧重“试探-回退”,在轻微丢包 + 中 RTT 场景会显得保守。BBR 则依据链路的 带宽-时延积(BDP) 建模,追求“以最小队列占用跑满可用带宽”。它需要准确的节拍(pacing),因此推荐结合 fq 队列规则 使用。
重点:BBR ≠ 降 RTT,它的强项是在丢包时保持高吞吐与短队列,应用层观感(TTFB、首屏)会显著改善。
实操步骤(Ubuntu 20.04)
下列命令需要 root 或 sudo 权限。
1. 确认内核版本与模块
uname -r
# 期望:5.4.x-xx-generic 或更高
# 查看是否有 bbr、cubic、reno 可用
sysctl net.ipv4.tcp_available_congestion_control
# 期望输出包含 bbr
# 如未包含,检查模块
lsmod | grep bbr || true
modprobe tcp_bbr # 临时加载
lsmod | grep bbr
坑 1:缺少模块包
某些云镜像裁剪了 sch_fq 和 tcp_bbr 到 linux-modules-extra-* 包里。若 modprobe tcp_bbr 报 “Module not found”:
apt update
apt install -y linux-modules-extra-$(uname -r)
modprobe tcp_bbr
2. 启用 fq 队列 + BBR(持久化)
新建或编辑 /etc/sysctl.d/99-bbr.conf:
cat >/etc/sysctl.d/99-bbr.conf <<'EOF'
# 为 BBR 配置推荐的默认队列与拥塞控制
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
# 可选:轻度优化缓冲/窗口(保守值,生产可逐步灰度)
net.ipv4.tcp_rmem = 4096 131072 6291456
net.ipv4.tcp_wmem = 4096 131072 6291456
net.ipv4.tcp_mtu_probing = 1
EOF
加载配置:
sysctl --system
sysctl net.core.default_qdisc
sysctl net.ipv4.tcp_congestion_control
# 期望:fq / bbr
验证 fq 是否生效(观察设备队列):
tc qdisc show dev eth0
# 期望有 "fq"(不是 fq_codel/codel)
坑 2:容器内无效
如果你是在 Docker/LXC 容器里改这些参数,最终起作用的是宿主机内核。容器里改好了不生效,请登录宿主机重复以上步骤。
3. 开机自动加载 BBR 模块(稳妥)
echo tcp_bbr >/etc/modules-load.d/bbr.conf
4.(可选)升级 HWE 内核
如果你想顺带获得更好的驱动/bugfix,可升级到 HWE 5.15:
apt install -y linux-generic-hwe-20.04
reboot
# 升级后重复第 1~3 步验证
5. 验证连接是否使用 BBR
新开一个跨境连接(例如从北京侧 curl 下载),在香港服务器上用 ss 看 TCP 信息:
ss -ti '( dport = :443 )'
# 看到 "cong bbr" 字样即为 BBR
也可以针对特定五元组过滤:
ss -ti dst <CLIENT_IP>
进阶:与 Nginx / 应用栈的配合
Nginx:无需特别改动;若有大文件下载,可开启 sendfile on; 并注意 tcp_nopush on;/tcp_nodelay on; 的配合(大对象走 sendfile,小对象走 nodelay)。
HTTP/2:BBR 改善的是内核侧 TCP 行为,对 H2 多路复用下的“队头阻塞”也有缓解(因为队列更短,丢包恢复更快)。
QUIC/HTTP/3:QUIC 使用用户态拥塞控制(与内核 TCP 无关),此文不展开。你的跨境主要仍是 TCP 流量时,BBR 收益更直接。
灰度与回滚
生产上我没有一把梭,按业务权重 逐台/逐池灰度:
先在一台边缘节点启用 BBR,观察 1–2 小时指标(重传率、TTFB p95、nginx upstream 响应分布、内核软中断占比)。
指标无回退扩大到半池。
需要回滚时仅需:
sysctl -w net.ipv4.tcp_congestion_control=cubic
# 或者把 99-bbr.conf 改回 cubic + fq_codel,再 sysctl --system
结果:启用 BBR 后的对比(同样 30 分钟窗口)
1)跨境吞吐(iperf3,相同参数)
| 指标 | 启用前(Cubic) | 启用后(BBR) | 变化 |
|---|---|---|---|
| 平均吞吐 | 190–220 Mbps | 420–520 Mbps | ↑ ~2.3× |
| 重传率 | 1.5–2.2% | 0.7–1.2% | ↓ 40–60% |
| RTT(mtr 中位) | 48–55ms | 45–52ms | 略降 |
RTT 本身变化不大,但队列占用更短,恢复更快。
2)Web 端到端(跨境用户)
| 指标 | p50(前→后) | p95(前→后) | 变化 |
|---|---|---|---|
| TTFB(动态 API) | 210→150ms | 620→260ms | p95 ↓ ~58% |
| 首屏可交互 | 1.2s→1.0s | 2.8s→1.9s | p95 ↓ ~32% |
| 下载 100MB | 6.8s→3.2s | 12.5s→6.1s | p95 ↓ ~51% |
主观体验:页面“抽顿感”明显减少,视频起播更稳。
线上踩坑与解决
坑 A:fq 不可用(qdisc 显示 pfifo_fast 或 fq_codel)
现象:tc qdisc show dev eth0 没有 fq,sysctl net.core.default_qdisc=fq 也不生效。
原因:sch_fq 模块缺失或内核裁剪。
处理:apt install linux-modules-extra-$(uname -r),modprobe sch_fq,再 sysctl --system。
坑 B:云平台的“智能网卡加速”与 pacing 冲突
现象:启用 BBR 后吞吐无提升,甚至更差。
定位:X710 开了某些 offload(如过 aggressive 的 TSO/GRO/LLC 组合)与 pacing 掐架。
处理:用 ethtool -k eth0 查看,适度关闭/开启:
ethtool -K eth0 gso on gro on tso on # 大多数情况保留
# 若异常,可尝试逐项 off 验证
坑 C:容器 / 宿主机混淆
现象:容器里显示 bbr,但跨机测试无提升。
原因:实际走的是宿主机 TCP 栈,容器设置不起作用。
处理:到 宿主机 配置 BBR。
坑 D:队列过大引起尾延迟
现象:BBR 后 p95 TTFB 仍然高。
排查:/proc/net/softnet_stat 里 dropped 升高,网卡队列/中断抢占不合理。
处理:适当调小 txqueuelen/RPS/RFS,均衡 IRQ 亲和;示例:
ip link set eth0 txqueuelen 2000
# irqbalance 开启,必要时手动做 CPU 亲和
我实际采用的保守型内核参数(供参考)
不同业务要 A/B:不要一次性全开。下面是我在源站上的“稳妥集”。
# /etc/sysctl.d/99-bbr.conf(附加)
net.core.somaxconn = 1024
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 10000 65535
net.core.netdev_max_backlog = 250000
net.core.rmem_max = 8388608
net.core.wmem_max = 8388608
一键自检脚本(上线前后都能跑)
把下面的脚本存为 check_bbr.sh:
#!/usr/bin/env bash
set -e
echo "== Kernel =="
uname -a
echo "== Congestion Control =="
sysctl net.ipv4.tcp_congestion_control
sysctl net.ipv4.tcp_available_congestion_control
echo "== Default qdisc =="
sysctl net.core.default_qdisc
tc qdisc show dev eth0 || true
echo "== Modules =="
lsmod | egrep 'bbr|sch_fq' || true
echo "== Nginx (if any) =="
ps aux | grep -E '[n]ginx' || echo "nginx not running"
echo "== Sample active TCP (first 5) =="
ss -ti '( dport = :443 )' | head -n 50 || true
echo "== Done =="
执行:
chmod +x check_bbr.sh
./check_bbr.sh
FAQ:几个常见问题
Q1:BBR 会不会对本地(香港本地/东南亚)用户变差?
一般不会,BBR 会维持较短的排队延迟;若本地用户极少丢包,体验通常不受影响或略好。
Q2:fq 和 fq_codel 选哪个?
BBR 官方推荐 fq,因为它支持精确 pacing;fq_codel 主打控延迟,但与 BBR 的节拍目标略不同。跨境吞吐 + 端到端延迟观感,我在实测里更偏 fq。
Q3:怎么只给一台/一组业务启用?
拥塞控制是 系统级 的;若要对特定业务做不同策略,建议用独立主机或 VM。
结尾:凌晨 3 点的机房走廊
启用 BBR 的 20 分钟后,前端的 p95 TTFB 从 600ms 掉到了 300ms 以下,下载速度也稳定翻倍。
我在机房走廊上伸了个懒腰,空调的风有点冷,但心是热的。
第二天白天,客服群里没了“卡顿”的抱怨,多了几句“昨天怎么突然好快”。这事儿没人会记很久,但作为运维,我知道,这一夜我们把链路的潜力又榨出了几分。
Checklist(拿去即用)
- uname -r ≥ 4.9(Ubuntu 20.04 默认 OK)
- linux-modules-extra-$(uname -r) 已安装
- /etc/sysctl.d/99-bbr.conf:default_qdisc=fq、tcp_congestion_control=bbr
- sysctl --system 后验证:tc qdisc show dev eth0 有 fq
- ss -ti 确认活跃连接 cong bbr
- 逐台灰度,上线 30–60 分钟观察 p95 TTFB/重传率/CPU 软中断
- 准备回滚命令:sysctl -w net.ipv4.tcp_congestion_control=cubic
如果你也在香港或其他跨境节点折腾网络体验,不妨按这套流程先跑一轮基线,再上 BBR 做 A/B。优化的尽头是度量——愿我们少点玄学,多点确定性