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

这个报错说明内核 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_allocated和tcp_memory_pressure; - 若
tcp_memory_allocated长期接近或超过tcp_mem[2](high 值),说明上限太低或连接太多/太“胖”; - 若
tcp_memory_pressure持续为 1,说明长期处于 pressure 状态,缓冲区被频繁压缩,影响吞吐和延迟; - 检查是否有大量长连接且
net.ipv4.tcp_rmem或net.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_rmem和net.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/snmp中Tcp:行的OutOfWindowIcmps、EarlyRetrans等指标,辅助判断是否真因内存不足丢包。










