Nginx 通过请求/连接池绑定内存生命周期、小块偏移分配+大块独立管理、高频对象复用与静态预分配、严控第三方模块等手段规避内存碎片。

核心思路是让所有临时内存严格绑定请求或连接生命周期,用整批创建销毁代替逐块释放——Nginx 不是“防碎片”,而是通过不回收小块来绕过碎片产生的前提。
严格使用请求池与连接池
每个 HTTP 请求必须用 r->pool,每个 TCP 连接必须用 c->pool。所有 headers、buf、结构体都走 ngx_palloc 或 ngx_pcalloc,禁止在模块或 Lua 脚本中调用 malloc、strdup、asprintf 等 libc 分配函数,否则直接落入 glibc 堆,成为隐式碎片源。
结构体优先用 ngx_pcalloc,自动清零,避免脏内存越界;SSL 缓存等长期数据若误挂到 r->pool,会导致 keepalive 场景下池持续膨胀。
小块偏移分配 + 大块独立管理
小块(≤4095 字节)在线性池中仅靠移动 last 指针分配,无锁、无元数据、无对齐浪费;大块(如上传 body)走独立 large 链表,由 malloc 单独申请,不污染主池。
这种分流天然避开 ptmalloc 的三重开销:空闲链表维护、块分割合并、多线程锁竞争。压测时若 pmap -x PID 显示 anon-rss 阶梯上涨、mmap 区域增多,大概率是大块误入主池或第三方模块触发了隐式堆分配。
高频对象复用与静态缓冲预分配
ngx_chain_t 和 ngx_buf_t 是碎片高发点。别每次调 ngx_alloc_chain_link,改用 ngx_chain_get_free_buf(r->pool) 复用空闲节点。
HTTP 状态行、常见 header(如 "Content-Type: text/plain")应预分配为全局静态 buffer,或在模块 postconfiguration 阶段一次性分配,避免 per-request 重复创建。
启用 sendfile 或 directio,让文件数据直通 socket,跳过用户态中间 buffer,天然减少分配压力。
严控第三方模块与 Lua 脚本行为
多数内存碎片不出在 Nginx 核心,而出在扩展逻辑中。检查 Lua-nginx-module、headers-more 是否触发 string.format、table.concat 或 Lua GC;拼接字符串优先用预分配 buffer + string.sub,而非动态分配。
缓存类操作改用 ngx.shared.DICT,而非 Lua table;编译时加 -DNGX_DEBUG_MALLOC,运行期用 addr2line 定位非 pool 分配点;error log 中出现 "ngx_chain_get_free_buf: no free buf",说明 chain 复用机制已失效。



















