Nginx内存池专为高并发短生命周期请求设计,采用整批创建销毁与线性分配规避碎片和系统调用开销;按请求/连接绑定生命周期,小块内存偏移分配,大块走large链表,强制使用pool-aware接口并禁止跨请求传递pool指针。

Nginx 内存池机制不是为了通用内存管理,而是专为高并发、短生命周期请求场景设计的轻量级分配方案。它通过“整批创建、整批销毁”+“线性偏移分配”彻底规避传统 malloc/free 带来的碎片和系统调用开销,是 Nginx 稳定支撑万级并发的关键底层保障。
按请求/连接粒度绑定生命周期
每个 HTTP 请求(ngx_http_request_t)或 TCP 连接都拥有独立内存池,由 ngx_create_pool() 创建,随请求结束自动调用 ngx_destroy_pool() 彻底释放。这种“归属即销毁”的模型消除了单个对象释放顺序问题,也杜绝了因 free 乱序导致的堆碎片。
- 小块内存(≤4KB 默认阈值)在线性池中靠移动
last指针分配,无元数据、无对齐浪费,cache line 友好 - 大块内存(如上传 body 缓存)走独立
large链表,用malloc单独申请,避免撑爆主池或造成内部碎片 - 池不可局部释放或 realloc,符合“请求级原子性”,不追求灵活,换得确定性
统一使用 pool-aware 分配接口
所有模块必须用 ngx_palloc / ngx_pcalloc 替代 malloc / calloc,确保内存归属清晰、生命周期可控。尤其注意:
- 结构体分配优先选
ngx_pcalloc,自动清零,避免脏内存引发未定义行为 - 禁止跨请求传递 pool 指针——请求销毁后池内存已失效,继续访问必崩溃
- 定时器回调、异步事件中若需内存,必须显式创建子池或复用 cycle->pool,绝不能误用 request pool
缓冲区与链表的复用策略
HTTP 处理中大量使用 ngx_buf_t 和 ngx_chain_t,反复新建/销毁链节点是碎片常见源头。
- 复用空闲 chain 节点:用
ngx_chain_get_free_buf()获取已有节点,而非每次ngx_alloc_chain_link() - 固定长度头字段(如
HTTP/1.1 200 OK、Content-Type)采用静态 buffer 池或模块级预分配池,避免 per-request 分配 - 启用
sendfile或directio时,数据直接从文件描述符送入 socket,绕过用户态 buffer,天然减少中间分配压力
警惕第三方模块引入的隐式堆分配
部分扩展模块(如 Lua-nginx-module、headers-more)可能在逻辑中调用 strdup、asprintf 或触发 Lua GC,破坏内存池隔离性。
- 检查源码是否含 libc 分配函数;优先选用提供 pool-aware 接口的版本(如用
ngx.shared.DICT替代 Lua table 缓存) - Lua 脚本中限制
string.format、table.concat频次,改用预分配 buffer +string.sub拼接 - 编译时启用
NGX_DEBUG_MALLOC,配合addr2line定位非 pool 分配源头
运行期可通过 nginx -s reload 后 RSS 是否持续爬升来验证效果——稳定服务数小时后内存仍缓涨,大概率存在 pool 或 large 块泄漏。这套机制不复杂,但容易忽略边界约束。


















