nginx高并发内存优化核心在于协同控制worker_connections与upstream keepalive:前者按峰值×1.2设上限(如3万连接配32768),避免单连接424字节开销引发碎片;后者启用keepalive 200并配合http/1.1头清理,以长连接池替代百亿级短连接导致的内核缓冲频繁分配与glibc堆碎片。

连接池本身不是 Nginx 内置的“可配大小”对象,真正影响高并发下内存碎片的关键,是 worker_connections 与 upstream keepalive 的协同配置——前者控制单 worker 进程承载的连接总数(含客户端+后端),后者决定反向代理层复用连接的能力。盲目调大连接数反而加剧碎片,核心在于“控总量、促复用、避短连”。
worker_connections:按需设上限,别堆数量
每个连接在 Nginx 中对应一个 ngx_connection_t(约 232 字节)+ 一对读写事件结构体(共约 192 字节),即单连接基础开销约 424 字节。若设为 65536,仅连接结构就占 27MB/worker;64 核机器启 64 个 worker,光这一项就超 1.7GB,且大量空闲连接会持续占用池内 buffer,放大碎片风险。
- CPU 核心 ≥ 16 时,显式设
worker_processes 8或12,避免进程过多导致上下文切换和内存池分裂 -
worker_connections按单机实际峰值连接 × 1.2 设置,例如支撑 3 万长连接,设32768即可,不建议直接拉到 65536 - 必须同步调大系统级限制:
worker_rlimit_nofile≥worker_connections × worker_processes,并检查/proc/sys/fs/nr_open
upstream keepalive:用长连接池替代短连接风暴
默认 proxy 是“每请求建一连”,百亿请求 = 百亿次 TCP 握手 + TIME_WAIT + 每次分配 socket 缓冲(4–8KB 内核 + proxy buffer 用户态)。这不仅是性能瓶颈,更是内存碎片主因——频繁 malloc/free 触发 glibc 堆碎片。
- 在
upstream块中启用连接池:keepalive 200;(建议值 100–300,依后端吞吐能力微调) - 配套强制 HTTP/1.1 并清理 Connection 头:
proxy_http_version 1.1;+proxy_set_header Connection ""; - 后端 keepalive timeout(如 Tomcat
connectionTimeout=60000)需比 Nginxproxy_read_timeout长 5 秒以上,避免主动断连导致后端连接泄漏
缓冲区与 header 分配:收缩边界,防恶意触发
缓冲区参数看似独立,实则直接影响内存池生命周期。large_client_header_buffers 4 8k 表示最多分配 4×8KB,但若攻击者发送超长 UA 或 Cookie,Nginx 会逐块申请 large 链表内存,这些 malloc 出来的块无法被 pool 批量回收,成为稳定碎片源。
- 收紧 header 缓冲:
client_header_buffer_size 1k;+large_client_header_buffers 2 2k;(总上限 4KB) - body 缓冲按业务设限:
client_max_body_size 10m;+client_body_buffer_size 2k;(小文件走内存,大文件直落磁盘) - proxy 缓冲分层控制:
proxy_buffer_size 4k;(头) +proxy_buffers 8 8k;(体) +proxy_busy_buffers_size 16k;(高负载缓冲水位)
验证是否生效:盯住 anon-rss 和 large 链表
所有配置都得靠运行数据确认效果。压测中定期执行 pmap -x PID,重点看:
-
anon-rss是否阶梯上涨(说明有未释放内存或 new 多于 free) -
mmap区域是否持续增多(glibc fallback 到 mmap 分配,典型碎片信号) - error log 中是否出现
"ngx_chain_get_free_buf: no free buf"(chain 复用机制失效) - 编译时加
-DNGX_DEBUG_MALLOC,配合addr2line定位非 pool 分配点,尤其查 Lua 脚本和第三方模块











