tcp_rmem和tcp_wmem三元组应按min default max设置,其中min为硬下限(通常4096),default决定初始窗口和慢启动行为,max需≥2×bdp且不超net.core.rmem_max/wmem_max。

tcp\_rmem 和 tcp\_wmem 的三元组到底怎么填
Linux TCP 接收/发送缓冲区由 tcp_rmem 和 tcp_wmem 控制,它们都是空格分隔的三个整数:min default max。这不是“最小值、默认值、最大值”的简单设定,而是一套动态调节策略——内核会根据 socket 当前状态(如 RTT、丢包、应用读写节奏)在这三者之间浮动调整实际缓冲区大小。
常见错误是直接抄网上“调大就快”的三元组,比如 4096 65536 16777216,结果在小带宽低延迟局域网里反而触发过度缓冲(bufferbloat),RTT 拉高、交互卡顿;或者在高吞吐长肥管道(long fat network)上因 max 不足被限速。
-
min是每个 socket 初始化时的硬下限,也用于计算接收窗口初始通告值(min太小会导致 SYN-ACK 窗口过小,影响建连后首波传输) -
default是 socket 创建时的起始值,也是 sysctl 默认生效值,但会被内核动态覆盖——它不等于“稳定运行值” -
max是单 socket 缓冲区可膨胀到的上限,受net.core.rmem_max/net.core.wmem_max约束(若后者更小,则以它为准)
不同网络场景下的经验值分层逻辑
没有放之四海皆准的数字,只有匹配链路特性的分层思路:关键看带宽 × 延迟积(BDP)。缓冲区至少要能装下 1–2 个 BDP 的数据,否则无法打满带宽;但也不能远超 BDP,否则排队延迟恶化。
示例对比:
局域网(1Gbps,0.1ms RTT)→ BDP ≈ 12.5KB 长距离公网(100Mbps,50ms RTT)→ BDP ≈ 625KB 数据中心 RDMA 网络(100Gbps,5μs RTT)→ BDP ≈ 62.5KB
- 低延迟局域网(RTT 4096 16384 65536 ——
max控制在 64KB 内,避免冗余排队 - 常规公网(RTT 20–100ms):
4096 262144 4194304(4K/256K/4M)—— 覆盖百兆级 BDP,default设为 256K 避免慢启动期窗口过小 - 高吞吐长肥管道(如科研网络、云间专线):
4096 1048576 16777216(4K/1M/16M)——max必须 ≥ 2×BDP,且需同步调大net.core.rmem_max
为什么 default 值常被忽略却最关键
default 不是“建议值”,而是 TCP 栈初始化 socket 时真正写入 sk->sk_rcvbuf / sk->sk_sndbuf 的初始值。它直接影响:三次握手窗口通告、慢启动初始拥塞窗口(cwnd)增长步长、应用第一次 read()/write() 的缓冲能力。
典型坑:把 default 设得太低(如沿用老系统默认的 212992 = 208KB),在千兆以上链路上,TCP 连接建立后头几轮 RTT 就因窗口不足而停滞;设得太高(如 4M),又会让小连接白白占用内存、触发更激进的内存压力回收。
- 现代内核(5.4+)对
default更敏感,尤其启用了tcp_slow_start_after_idle=0时,该值决定空闲后重启的起点 - 若应用使用
setsockopt(..., SO_RCVBUF, ...)手动设缓冲区,会绕过tcp_rmem的default,但受限于net.core.rmem_max - 检查当前生效值:读
/proc/sys/net/ipv4/tcp_rmem,注意第三列是max,不是全局上限
改完必须验证的三件事
修改 /etc/sysctl.conf 后执行 sysctl -p 只是加载参数,不代表所有 socket 都立刻按新规则运行。真实效果取决于连接何时建立、路径 MTU、是否启用 tcp_window_scaling 等。
- 确认
tcp_window_scaling已开启(cat /proc/sys/net/ipv4/tcp_window_scaling应为 1),否则窗口无法突破 64KB,max再大也无效 - 用
ss -i查看具体连接的rcv_space和snd_space,它反映当前动态缓冲区大小,不是配置值 - 压测时监控
/proc/net/snmp中的TcpExt: TCPAutoCorking和TcpExt: TCPOrigDataSent,若前者突增,说明缓冲区过大导致内核频繁合包,反而降低效率
缓冲区调优永远在“填满管道”和“不让数据排队”之间找平衡点,而这个点随流量模式实时漂移。最稳的做法是先按 BDP 设好 max,再用 default 控制冷启动行为,min 则保持 4K 不动——它只在极低内存或特殊协议栈路径里起作用,别乱动。










