在没有打开bbr之前。IPerf3结果如下:分别是单线程和多线程。为什么差距巨大?

5]   7.00-8.00   sec  2.50 MBytes  21.0 Mbits/sec    2    218 KBytes       
[  8]   7.00-8.00   sec  8.75 MBytes  73.4 Mbits/sec    0    628 KBytes       
[ 10]   7.00-8.00   sec  7.50 MBytes  62.9 Mbits/sec    0    421 KBytes       
[SUM]   7.00-8.00   sec  18.8 MBytes   157 Mbits/sec    2             
- - - - - - - - - - - - - - - - - - - - - - - - -
[  5]   8.00-9.00   sec  2.50 MBytes  21.0 Mbits/sec    0    245 KBytes       
[  8]   8.00-9.00   sec  7.50 MBytes  62.9 Mbits/sec    0    630 KBytes       
[ 10]   8.00-9.00   sec  6.25 MBytes  52.4 Mbits/sec    0    457 KBytes       
[SUM]   8.00-9.00   sec  16.2 MBytes   136 Mbits/sec    0             
- - - - - - - - - - - - - - - - - - - - - - - - -
[  5]   9.00-10.00  sec  3.75 MBytes  31.5 Mbits/sec    0    261 KBytes       
[  8]   9.00-10.00  sec  8.75 MBytes  73.4 Mbits/sec    0    639 KBytes       
[ 10]   9.00-10.00  sec  7.50 MBytes  62.9 Mbits/sec    0    520 KBytes       
[SUM]   9.00-10.00  sec  20.0 MBytes   168 Mbits/sec    0             
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.05  sec  35.9 MBytes  29.9 Mbits/sec  442             sender
[  8]   0.00-10.05  sec  82.8 MBytes  69.0 Mbits/sec  1050             sender
[ 10]   0.00-10.05  sec  69.6 MBytes  58.1 Mbits/sec  1629             sender
[SUM]   0.00-10.05  sec   188 MBytes   157 Mbits/sec  3121             sender
-----------------------------------------------------------
Server listening on 5201 (test #3)
-----------------------------------------------------------
 56512
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  1.32 MBytes  11.1 Mbits/sec    3   43.2 KBytes       
[  5]   1.00-2.00   sec   502 KBytes  4.11 Mbits/sec    4   16.7 KBytes       
[  5]   2.00-3.00   sec   251 KBytes  2.06 Mbits/sec    4   8.37 KBytes       
[  5]   3.00-4.00   sec   251 KBytes  2.06 Mbits/sec    1   13.9 KBytes       
[  5]   4.00-5.00   sec   251 KBytes  2.06 Mbits/sec    2   18.1 KBytes       
[  5]   5.00-6.00   sec   251 KBytes  2.06 Mbits/sec    3   9.76 KBytes       
[  5]   6.00-7.00   sec   251 KBytes  2.06 Mbits/sec    2   9.76 KBytes       
[  5]   7.00-8.00   sec   251 KBytes  2.06 Mbits/sec    1   15.3 KBytes       
[  5]   8.00-9.00   sec   251 KBytes  2.06 Mbits/sec    2   16.7 KBytes       
[  5]   9.00-10.00  sec   251 KBytes  2.06 Mbits/sec    1   20.9 KBytes  

这是一个非常经典的长肥网络(LFP, Long-Fat Pipe)在没有优化情况下的表现。单线程和多线程之所以差距如此巨大(2.06 Mbps vs 157 Mbps),是因为传统 TCP 算法(如 CUBIC)在“高延迟+轻微丢包”环境下的天然缺陷。

以下是详细的分析:

1. 传统算法对丢包的“过度反应”

在没有开启 BBR 之前,你的 VPS 默认使用 CUBIC 或 Reno 算法。这些算法的核心逻辑是:丢包 = 拥塞。

  • 单线程: 观察你的单线程数据,每秒都有 1-4 次重传(Retr)。一旦 CUBIC 监测到一个丢包,它会认为网络“堵死了”,立刻将拥塞窗口(Cwnd)砍掉一半甚至更多(比如从 43KB 直接降到 8.37KB)。
  • 后果: 你的窗口还没等爬升起来,下一个丢包又来了。结果就是 Cwnd 始终被压制在几 KB 到几十 KB 之间,速度自然锁死在 2 Mbps 左右。

2. 高延迟(200ms)放大了恢复难度

TCP 窗口的增长是需要时间的(每一个 RTT 往返才增长一点)。

  • 由于你的延迟高达 200ms,这意味着一秒钟内窗口只能进行 5 次“反馈循环”。
  • 如果窗口被砍掉,它需要好几秒钟才能恢复到之前的水平。但在不稳定的长途线路上,几秒钟内几乎肯定会再次发生微小丢包。
  • 数学直观: $Bitrate = \frac{Cwnd}{RTT}$。当 $Cwnd$ 被限制在 20 KB 时,你的理论速度就是 $\frac{20 \text{ KB}}{0.2 \text{ s}} \times 8 \approx 0.8 \text{ Mbps}$。这和你看到的 2 Mbps 非常吻合。

3. 多线程为什么能“力大砖飞”?

多线程(-P 3)之所以能跑到 157 Mbps,是因为它在物理层面上“作弊”了:

  • 风险分担: 每个线程都有自己独立的 $Cwnd$。当线程 A 因为丢包而减速时,线程 B 和 C 可能正处于高速阶段。
  • 独立恢复: 三个线程同时在“抢”带宽,即便每个线程都因为丢包而表现不佳,但它们累加起来的窗口总和远大于单个线程能达到的上限。
  • 观察重传数: 你的多线程测试在 10 秒内产生了 3121 次重传。这证明了链路上其实有很多丢包或抖动,单线程会被这些重传彻底“吓死”,而多线程靠着数量优势强行把数据塞了过去。

4. 数据对比总结

特性单线程 (Thread 5)多线程 (SUM)
平均速率2.06 Mbits/sec157 Mbits/sec
Cwnd 表现极小且持续萎缩 (8.37K - 43K)多个线程窗口互补,总和较大
重传影响致命,导致连接进入持续的“慢启动”或“拥塞避免”较大,但被多连接的并行性抵消

这就是为什么要开 BBR

BBR 的革命性在于:它不再把丢包当作拥塞的唯一信号。

  • BBR 会测量延迟和带宽,只要它认为管道还没满,即便有丢包,它也会维持甚至增加发送速率。
  • 如果你现在开启 BBR,你会发现单线程的速度会立刻从 2 Mbps 飙升到接近多线程的水平(甚至更高)。