直接调大tcp_rmem/wmem未必提升性能,需结合带宽、rtt和业务模式计算合理缓冲区上限;验证需查sysctl值、ss -i实际窗口及net.core.*_max限制,并排除window_scaling、应用层覆盖等干扰因素。

直接调大 tcp_rmem 和 tcp_wmem 数值不一定提升性能,反而可能浪费内存、增加延迟;真正有效的调优必须结合带宽、RTT 和业务连接模式来算出合理缓冲区上限。
怎么看当前 TCP 缓冲区设置是否合理
先查真实值,别凭经验猜:
-
sysctl net.ipv4.tcp_rmem和sysctl net.ipv4.tcp_wmem输出三个数字:最小值、默认值、最大值(单位字节) - 对比
net.core.rmem_max和net.core.wmem_max—— 如果后者更小,tcp_rmem的最大值实际会被截断 - 用
ss -i查单个连接的实际接收/发送窗口大小,看是否长期卡在默认值没涨起来(说明自动缩放没生效或被限制)
为什么增大 tcp_rmem 最大值后吞吐没变
常见原因不是“没改”,而是被其他参数拦住了:
-
net.ipv4.tcp_window_scaling必须为 1,否则窗口无法突破 64KB -
net.ipv4.tcp_rmem的第三个值(最大值)必须 ≥ 带宽 × RTT(即 BDP),否则内核不会分配足够空间 - 应用层未启用 SO_RCVBUF/SO_SNDBUF 或设了固定值,会绕过内核自动调节逻辑
- 网卡驱动或硬件不支持大包或 RSS 均衡,导致单核瓶颈,缓冲区再大也压不上去
短连接服务(如 API 网关)最该调的几个参数
这类场景瓶颈常在端口耗尽和连接建立/关闭开销,而非吞吐:
- 启用
tcp_tw_reuse=1,但必须同时开启tcp_timestamps=1,否则无效且可能引发连接失败 - 缩小
tcp_fin_timeout到 30–45 秒,加速 TIME_WAIT 回收 - 扩大
ip_local_port_range至1024 65535,避免connect: Cannot assign requested address -
tcp_slow_start_after_idle设为 0 没意义——短连接根本等不到空闲就断了
长连接服务(如 gRPC、数据库连接池)要注意缓冲区“够用”而非“越大越好”
缓冲区过大反而拖慢响应,尤其对小包高频交互场景:
- 接收缓冲区最大值建议设为 BDP 的 1.2–1.5 倍,例如 10Gbps + 0.5ms RTT → BDP ≈ 6.25MB,
tcp_rmem第三项可设8388608(8MB) - 必须同步调高
net.core.rmem_max,否则tcp_rmem最大值形同虚设 - 开启保活:
tcp_keepalive_time=600、tcp_keepalive_intvl=75、tcp_keepalive_probes=9,防止中间设备静默断连 - 禁用空闲慢启动:
tcp_slow_start_after_idle=0,避免长连接静默后重传速率骤降
最易被忽略的是:所有缓冲区参数调整后,必须验证 ss -i 输出中单连接的 rcv_space 和 snd_space 是否真达到了预期值。没看到实际窗口扩大,就等于没调成。










