第三章 TCP 带宽测试:窗口大小对带宽的影响与缓冲区调优

大家好,我是老张。今天咱们聊聊 TCP 带宽测试里一个特别关键、也特别容易踩坑的话题——TCP 窗口大小。

说实话,我见过太多人拿着 iperf 跑个测试,看到带宽上不去就怪网络。其实很多时候,问题出在 TCP 窗口上。你想想看,TCP 就像一个水管,窗口大小就是水管的直径。直径太小,水流自然上不去。

3.1 TCP 窗口的基本概念

TCP 窗口,全称是 TCP 接收窗口(Receive Window,简称 RWIN)。它告诉发送方:「嘿,你最多能发这么多数据,不用等我确认。」

说白了,这就是一个流量控制机制。接收方告诉发送方自己还有多少缓冲区可用,发送方就按这个量来发。

核心公式:

带宽延迟积(BDP)= 带宽 × 往返时延(RTT)

理想窗口大小 ≥ BDP

举个例子。假设你的链路是 1Gbps,RTT 是 10ms。那么 BDP 就是:

BDP = 1,000,000,000 bps × 0.01 s = 10,000,000 bits = 1.25 MB

这意味着,你的 TCP 窗口至少得 1.25MB,才能把带宽跑满。如果窗口只有 64KB,那实际吞吐量最多也就 51.2Mbps。嗯,差了将近 20 倍。

3.2 窗口大小对带宽的影响

我在项目中遇到过一件事。有个客户说他们的专线带宽是 100Mbps,但实际传输文件只有 20Mbps。我上去一看,RTT 是 80ms,窗口大小还是默认的 64KB。

算一下:

最大吞吐量 = 窗口大小 / RTT = 64KB / 0.08s = 800KB/s ≈ 6.4Mbps

你看,连 20Mbps 都不到。这就是窗口太小导致的瓶颈。

为什么会这样?因为发送方发完一个窗口的数据后,必须等接收方确认才能继续发。窗口越小,等待确认的次数就越多,效率自然就低了。

窗口大小 RTT = 10ms RTT = 50ms RTT = 100ms
64KB 51.2 Mbps 10.2 Mbps 5.1 Mbps
256KB 204.8 Mbps 41.0 Mbps 20.5 Mbps
1MB 819.2 Mbps 163.8 Mbps 81.9 Mbps
4MB 3.2 Gbps 655.4 Mbps 327.7 Mbps

从这张表能看出来,RTT 越大,窗口大小的影响就越明显。长肥网络(Long Fat Network)里,窗口大小就是命根子。

3.3 如何调整 TCP 缓冲区

调整 TCP 缓冲区,说白了就是改几个内核参数。我个人习惯在 Linux 系统上操作,因为灵活、可控。

3.3.1 Linux 系统调优

Linux 的 TCP 缓冲区有三个关键参数:

  • net.core.rmem_default:接收缓冲区默认大小
  • net.core.wmem_default:发送缓冲区默认大小
  • net.core.rmem_max 和 net.core.wmem_max:最大缓冲区大小

还有一组是 TCP 专用的:

  • net.ipv4.tcp_rmem:接收缓冲区(最小值、默认值、最大值)
  • net.ipv4.tcp_wmem:发送缓冲区(最小值、默认值、最大值)

我建议这样设置:

# 调整系统级缓冲区
sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.wmem_max=16777216
sysctl -w net.core.rmem_default=262144
sysctl -w net.core.wmem_default=262144

# 调整 TCP 缓冲区
sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"
sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216"

# 启用窗口缩放
sysctl -w net.ipv4.tcp_window_scaling=1

小提示:窗口缩放(Window Scaling)必须开启。否则窗口最大只能到 64KB,调再大也没用。我见过有人改了缓冲区大小但忘了开缩放,折腾了半天才发现。

3.3.2 Windows 系统调优

Windows 下调整稍微麻烦点,得改注册表:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

# 设置 TCP 窗口大小
TcpWindowSize = DWORD (十进制,单位字节)
# 例如 16777216 表示 16MB

# 启用窗口缩放
Tcp1323Opts = DWORD (3 表示启用所有选项)

改完记得重启。嗯,Windows 嘛,你懂的。

3.4 实战:用 iperf 测试窗口影响

光说不练假把式。咱们用 iperf 实际测一下。

先启动服务端:

iperf3 -s -p 5201

客户端测试,默认窗口:

iperf3 -c 192.168.1.100 -p 5201 -t 30

然后手动指定窗口大小:

iperf3 -c 192.168.1.100 -p 5201 -t 30 -w 1M

对比两次结果。我敢打赌,如果 RTT 比较大,第二次的带宽会明显提升。

注意:iperf 的 -w 参数设置的是 TCP 窗口大小,但实际生效的是 min(发送端窗口, 接收端窗口)。所以两端都要调大才行。我曾经在测试时只调了客户端,服务端没动,结果带宽还是上不去。排查了半天才发现是服务端限制了窗口。

3.5 知识体系图

下面这张图总结了 TCP 窗口与带宽的关系:

TCP 窗口大小与带宽性能关系图 发送方 发送缓冲区 接收方 接收缓冲区 数据段(窗口大小控制) ACK 确认 窗口大小 = 接收方剩余缓冲区 发送方最多发这么多数据等待确认 影响因素 • 带宽(B) • 往返时延(RTT) • 缓冲区大小 性能结果 • 窗口 ≥ BDP → 带宽跑满 • 窗口 < BDP → 带宽受限 • 实际吞吐量 = 窗口 / RTT 核心结论:窗口大小 ≥ 带宽 × RTT,才能跑满带宽

3.6 避坑指南

最后,分享几个我踩过的坑:

  • 别盲目调大窗口:窗口太大,丢包重传的成本也高。我建议从 BDP 的 1.5 倍开始试。
  • 注意中间设备:有些防火墙、负载均衡器会改写 TCP 窗口。我曾经遇到过,调了半天客户端和服务端,结果中间设备把窗口给限制了。
  • 窗口缩放不是万能的:有些老设备不支持窗口缩放,得确认两端都支持。
  • 实测为准:理论算得再好,不如实际跑一次 iperf。我习惯在调优前后各测三次,取平均值对比。

一句话总结:TCP 窗口大小决定了你能用多少带宽。调优的核心就是让窗口 ≥ 带宽 × RTT。别偷懒,算清楚再动手。

好了,这一章就到这里。记住,调窗口是基本功,但也是很多性能问题的根源。下次遇到带宽上不去,先看看窗口大小对不对。

想要更多资料,联系可可