TCP out of memory — consider tuning tcp_mem 报错后的参数调整经验

10次阅读

TCP缓冲区内存耗尽需调优tcp_mem三元组:low为无压力阈值,pressure触发缓冲区收缩与延迟ACK,high超限则丢包拒连;应结合sockstat监控、连接数与单连接缓冲大小合理设值,并同步收紧tcp_rmem/wmem max及排查应用层读写瓶颈。

TCP out of memory — consider tuning tcp_mem 报错后的参数调整经验

这个报错说明内核 TCP 缓冲区内存耗尽,不是简单加内存就能解决,关键在 tcp_mem 三元组参数的合理设置——它控制的是每个 TCP socket 能用多少内存,以及内核何时开始施压、何时强制回收。

理解 tcp_mem 三个值的真实含义

tcp_mem 是一个由空格分隔的三整数数组,例如 196608 262144 393216,单位是页(通常一页为 4KB):

  • 第一个值(low):内存压力阈值下限。当所有 TCP socket 占用总内存 ≤ 此值时,内核完全不干预;
  • 第二个值(pressure):进入内存压力状态的起点。超过此值后,内核开始缩减 socket 的接收/发送缓冲区(通过 tcp_rmem/tcp_wmem 动态收缩),并可能延迟 ACK;
  • 第三个值(high):硬性上限。一旦总用量超过此值,内核会主动丢包、重置连接、拒绝新建连接(SYN 被丢),此时就触发了你看到的 “out of memory” 报错。

如何判断当前值是否合理

别只看报错,先查真实负载:

  • 运行 cat /proc/net/sockstat,重点关注 tcp_memory_allocatedtcp_memory_pressure
  • tcp_memory_allocated 长期接近或超过 tcp_mem[2](high 值),说明上限太低或连接太多/太“胖”;
  • tcp_memory_pressure 持续为 1,说明长期处于 pressure 状态,缓冲区被频繁压缩,影响吞吐和延迟;
  • 检查是否有大量长连接且 net.ipv4.tcp_rmemnet.ipv4.tcp_wmem 的 max 值设得过大(如 4MB),单个连接吃掉几十页,几百个连接就爆了。

调参建议与实操步骤

调整不是盲目放大,而是匹配业务特征:

  • 先确认系统页大小:getconf PAGESIZE(通常是 4096);
  • 估算合理 high 值:假设你有 2000 个活跃连接,平均每个连接缓冲区峰值用 256KB,则需约 2000 × 256KB = 512MB → 512×1024×1024 ÷ 4096 ≈ 131072 页;再留 30% 余量,high 设为 170000;
  • 按比例设 low 和 pressure:常见比例为 1 : 1.5 : 2.5,比如 68000 102000 170000
  • 同步收紧单连接上限:把 net.ipv4.tcp_rmemnet.ipv4.tcp_wmem 的第三个值(max)从几 MB 降到 512KB 或 1MB,避免个别连接霸占资源;
  • 写入生效:sysctl -w net.ipv4.tcp_mem="68000 102000 170000",并加入 /etc/sysctl.conf 持久化。

还要配合检查的关联项

tcp_mem 不是孤立参数:

  • 确认 net.ipv4.tcp_low_latency = 0(默认),避免干扰自动调优逻辑;
  • 若启用了 net.ipv4.tcp_congestion_control = bbr,注意 BBR 对缓冲区更敏感,pressure 状态下表现可能更激进;
  • 检查应用层是否未及时读取接收缓冲区(read() 慢)、或未及时发送导致发送队列积,这比调内核参数更治本;
  • 观察 /proc/net/snmpTcp: 行的 OutOfwindowIcmpsEarlyRetrans 等指标,辅助判断是否真因内存不足丢包。
text=ZqhQzanResources