Nginx内存池是为请求/连接级短生命周期定制的轻量方案:小块内存(≤4KB)在线性区移动last指针分配,无元数据和对齐开销;大块内存走独立large链表,调用malloc并挂入pool->large;整池绑定请求生命周期,销毁即清空,不支持逐块释放或realloc。

Nginx 架构中的内存池不是通用堆管理器,而是一套为“请求/连接级短生命周期”量身定制的轻量级方案。它用确定性换稳定性:小块内存(≤4KB)在线性区靠移动 last 指针分配,无元数据、无对齐开销;大块走独立 large 链表;整池绑定请求生命周期,销毁即清空——不逐块释放,也不支持 realloc。
按作用域严格划分生命周期
每个 TCP 连接创建 c->pool,每个 HTTP 请求创建 r->pool,定时器或异步回调需显式使用 cycle->pool 或新建临时子池。子请求必须建独立子池,不可复用父池指针。跨请求存活的数据(如共享字典、upstream 连接池)只能放在 cycle->pool 或共享内存中。
小块与大块的差异化分配路径
- ≤4KB 默认阈值内:调用
ngx_palloc或更安全的ngx_pcalloc(自动清零),分配仅移动指针,O(1) 完成 - >4KB:触发
ngx_palloc_large,底层调用malloc并挂入pool->large链表,确保池销毁时一并free - 禁止在小块区强行分配超限内存——会导致分配失败或越界,应主动降级走 large 路径
统一使用 pool-aware 接口,杜绝 libc 混用
所有模块必须用 ngx_palloc/ngx_pcalloc/ngx_pnalloc,禁用 malloc/calloc/strdup 等 libc 函数。否则会破坏归属关系,使池销毁后仍有指针指向已失效内存。
- 结构体优先选
ngx_pcalloc,避免未初始化字段引发未定义行为 - 第三方库(如 PCRE、OpenSSL)所需缓冲区,须用
ngx_pnalloc分配,并确认其不会尝试free - Lua 模块中慎用
string.format、table.concat,避免触发隐式堆分配
缓冲区与链表的复用降低碎片
HTTP 处理高频使用 ngx_buf_t 和 ngx_chain_t,反复新建节点是碎片常见源头。
- 复用空闲 chain 节点:调用
ngx_chain_get_free_buf()获取已有节点 - 固定长度头字段(如
"HTTP/1.1 200 OK")采用静态 buffer 池或模块级预分配 - 启用
sendfile或directio时,数据直通内核,绕过用户态 buffer,天然减少中间分配


















