兔洞博客
兔洞博客
个人博客

VPS TCP 调优实录:tcpfit/BBR 实测数据

上个月排查一台芝加哥 VPS 时遇到个典型问题:千兆端口,多线程 iperf3 能跑到 998M,但单线程死卡在 217M 左右,看 YouTube 高码率视频就转圈。机器不慢、带宽够、BBR 也开着——问题出在哪?

最后查明白是 TCP 发送缓冲太小,调完单线程直接拉到 253M。这篇把整个排查过程和实测数据整理出来,你自己遇到"节点速度上不去"时可以照着判断。

更新于 2026-08-26。工具版本以 tcpfit 的 GitHub 为准。

先说结论:三种情况,三种对策

你的症状病根调 TCP 有没有用
同机房互传都慢服务器缓冲区太小✅ 有用,主力战场
机房内快,国内连上去慢、重传高国际链路拥塞/丢包❌ 没用,物理瓶颈
单线程慢但多线程能跑满单流受 RTT×缓冲限制✅ 有用,就是本文主角

先做这个分流判断,再决定要不要动手调。很多人一上来就无脑跑一键脚本,方向错了白折腾。

一个公式:BDP 带宽时延积天花板

单条 TCP 连接的速度上限有个硬计算:

单流理论上限 = 发送缓冲区(bytes) × 8 ÷ RTT(秒)

这就是 BDP(Bandwidth-Delay Product,带宽时延积):缓冲区里最多囤这么多"在路上"的数据,RTT 越大,同样缓冲能撑的速度越低。

拿芝加哥那台算一遍:

发送缓冲 4MB,到东京 RTT 129ms
4 × 1024 × 1024 × 8 ÷ 0.129 ≈ 258 Mbps

实测 217M 卡死,和理论值 258M 对得上——不是线路不行,是缓冲装不下更多"在途数据"。这种情况下换协议、换内核都没用,把缓冲区加大就行。

反过来,RTT 小的时候这个公式基本不构成限制:

发送缓冲 11MB,同机房 RTT 8ms
11 × 8 ÷ 0.008 = 11000 Mbps ≈ 11 Gbps

缓冲根本用不满,瓶颈在别处(比如端口本身)。所以先算 BDP 再动手,一步就能判断该不该调。

第一步:定位瓶颈在哪一段

拿两台 VPS(或本机对远端)互跑 iperf3,两端都要装:

apt-get install -y iperf3        # 两端
iperf3 -s -p 39501               # 服务端
iperf3 -c <对端IP> -p 39501 -t 10        # 客户端单线程
iperf3 -c <对端IP> -p 39501 -t 8 -P 4    # 客户端 4 并发

端口用防火墙已放行的段,别为测试新开端口;测完 ss -tlnp | grep 39501 确认服务端停干净。

判读方法就一条:机房内(或近距离低 RTT)对跑快 = 服务器没问题;国内连过去慢且重传爆炸 = 国际链路的锅。

第二步:tcpfit 实际调优

服务器侧的问题交给 tcpfit 处理——2026 年 8 月发布在 NodeSeek 的开源脚本(MIT,约 1850 行 Shell),特点是按你实测的带宽和 RTT 推导参数,不是无脑套模板。

curl -fsSL https://raw.githubusercontent.com/Kylin010/tcpfit/main/tcpfit.sh -o /tmp/tcpfit.sh
chmod +x /tmp/tcpfit.sh
bash /tmp/tcpfit.sh tune --role proxy --bw 1000 --rtt 129

两个参数必须手动给准,自动探测经常不准:

  • --bw 填真实端口带宽。KVM 虚拟网卡读不到标称速率,不知道就先跑一次 sweep 实测
  • --rtt 用 ping 对端 的真实值,别信默认探测

它做的事:把 net.ipv4.tcp_wmem 上限按 BDP 拉大、开 BBR + fq 队列、关 tcp_slow_start_after_idle(长连接空闲后不再重新慢启动,代理场景很重要)等 32 项。改动只落 6 个位置,都有快照可回滚:

▸tcpfit 落地的 6 个位置(出问题回滚用)
  • /etc/sysctl.d/99-tcpfit.conf —— sysctl 参数主体
  • /var/lib/tcpfit/pre-tune.snapshot —— 调优前完整快照
  • tcpfit-qdisc.service + /usr/local/sbin/tcpfit-qdisc.sh —— fq 队列管理
  • networkd-dispatcher 里 50-tcpfit-initcwnd —— 初始拥塞窗口
  • /etc/modules-load.d/tcpfit-bbr.conf —— BBR 内核模块加载

回滚:bash tcpfit.sh rollback,一条命令恢复原状。跑之前建议先 tar 一份 /etc/sysctl.d/ 双保险。

▸第三方脚本的安全审查记录

跑陌生脚本前我 grep 了一遍危险命令,有两处容易误判的点说明一下:

  • dd if=/dev/zero —— 用于创建 swap 文件,正常功能
  • /dev/tcp/$host/5201 —— 探测 iperf3 端口是否在线,正常功能
  • 写 /etc/modules-load.d/ —— 加载 BBR 模块,正常功能

逐行看过上下文,没有外传数据、没有留后门动作。当然这是我的审查结论,介意的话只抄它的 sysctl 参数手改也一样。

实测数据:两台机器调优前后

案例一:芝加哥 → 东京(高 RTT,缓冲受限型)

项目调优前调优后
发送缓冲上限4 MB32.5 MB
BDP 理论单流上限≈258 Mbps≈2015 Mbps
iperf3 单线程实测217 Mbps 卡死253 Mbps
iperf3 4 并发—998 Mbps ≈ 千兆满速

RTT 129ms 下 BBR 单流 ~250M 是算法本身的物理极限,剩下的靠多连接补齐——这正是代理软件默认多连接的工作方式,所以实际体验提升非常明显。

案例二:东京 IIJ → 东京同机房(低 RTT,本来就健康)

项目数值
RTT8 ms
端口3 G
发送缓冲上限11 MB(BDP 天花板 ≈11G,远超端口)
iperf3 单线程2.19 Gbps
iperf3 4 并发3.04 Gbps ≈ 端口满速

这台调优前后几乎没差别——RTT 小的机器本来就不受缓冲限制,调了只是锦上添花。再次验证"先算 BDP"的价值:一眼就知道这台不用折腾。

泼冷水:国际链路的瓶颈,调优救不了

最关键的实测是这个。用国内的家用宽带盒子(Armbian 小主机)直连东京节点跑 iperf3:

单线程 54 Mbps / 4 并发 56 Mbps
重传 2075~22822 次 / RTT 268ms

同一台东京服务器,机房内 3 Gbps 满速,国内直连只有 54M 且重传上万——瓶颈在国际段拥塞,不在服务器。这种局面下 tcpfit、BBR、换协议全都无效,唯一的解法是绕路(中转/专线),也就是线路类型详解里讲的那套逻辑。

这也是我给机场评测定的一条铁律的由来:评测里的"速度快"必须区分是服务器快还是链路快。商家展示的服务器侧测速图再漂亮,也证明不了你连上去快。

附:真实线路测速的两个坑

写评测要拿真实数据时注意,这两个坑我都踩过:

  1. 别走 Tailscale 隧道测速。它的 MTU 只有 1280 且打洞失败会绕 DERP 中继,测出来的数字严重偏低。正确姿势:Tailscale 只当 SSH 管理通道,iperf3 走两端公网 IP 直连。
  2. 家宽对海外 UDP 经常限速。Hysteria2 这类 UDP 协议握手时通时断,先怀疑家宽 UDP QoS,别急着骂服务器。测速优先选 TCP 协议(vless-reality 等),结果稳定得多。

验证清单

调完收尾过一遍:

  • sysctl net.ipv4.tcp_wmem 上限已提升(和调优前快照对比)
  • sysctl net.ipv4.tcp_congestion_control 返回 bbr,default_qdisc 返回 fq
  • sysctl net.ipv4.tcp_slow_start_after_idle 返回 0
  • iperf3 服务端已停、端口已释放
  • 快照文件还在 /var/lib/tcpfit/pre-tune.snapshot,随时可回滚

相关阅读

翻墙技术分享