proxy模块使用的内存全部归属请求级内存池r->pool,该池随HTTP请求创建和销毁而自动分配与释放,无需手动回收。

在 Nginx 中,ngx_http_proxy_module 本身不直接管理独立的内存池,它复用 Nginx 核心的请求级内存池(r->pool)来分配临时缓冲区、头结构、上游连接上下文等资源。内存回收不是由 proxy 模块主动触发的,而是依赖于 Nginx 的内存池生命周期机制——即随 HTTP 请求周期自动释放。
proxy 模块使用的内存归属哪个池?
所有 proxy 相关的动态内存(如:proxy_pass 构造的 upstream URL、重写后的 header、临时 body 缓冲区、upstream conf 结构体副本、proxy buffer 链表节点等)均分配自当前请求的内存池 r->pool。该池在请求初始化时创建,在请求结束(无论成功、错误或超时)时被整体销毁。
- 例如:调用
ngx_palloc(r->pool, size)分配 header 缓存空间,或ngx_pcalloc初始化ngx_http_proxy_ctx_t - 即使启用
proxy_buffering off,部分控制结构仍使用r->pool,只是不分配大块 body 缓冲区
哪些 proxy 场景会额外申请内存?
以下操作会在请求池中产生显著内存开销,需关注其生命周期:
-
Header 处理:通过
proxy_set_header添加/覆盖 header 时,值字符串和新 header 结构体均从r->pool分配 -
URL 重写与变量展开:如
proxy_pass http://backend/$uri中的$uri展开结果、带变量的proxy_redirect值,均需池内存储 -
Upstream 负载均衡上下文:每个 upstream 请求会创建
ngx_http_upstream_t及其peer上下文,也挂载在r->pool上 -
Buffer 配置:当启用 buffering,
proxy_buffers和proxy_busy_buffers_size所定义的缓冲区内存虽由 slab 分配器管理,但其元数据(如ngx_chain_t链、buffer 描述符)仍在r->pool
没有显式“回收”,但有关键释放时机
Nginx 不提供类似 free() 的手动回收接口给模块使用。proxy 模块也不需要、也不应该尝试单独释放某块内存。真正有效的“回收”发生在以下时刻:
- 请求正常结束(返回响应后):
r->pool被ngx_destroy_pool(r->pool)彻底释放,所有子分配一并清空 - 请求被中断(客户端断连、超时、内部错误):Nginx 保证调用清理钩子(如
ngx_http_upstream_cleanup),释放上游连接、关闭 socket,并最终销毁r->pool - 子请求(subrequest)完成时:其专属子池(
sr->pool)被销毁,不影响主请求池
开发或调试时要注意什么?
若你在编写自定义 proxy 相关模块或 patch,务必遵守 Nginx 内存管理约定:
- 只使用
r->pool(或子请求的sr->pool)分配请求级资源;避免使用malloc或全局池 - 不要保存指向
r->pool内存的长期指针——请求结束后指针即失效 - 若需跨请求缓存数据(如 upstream 配置解析结果),应使用
cycle->pool或共享内存(shmtx+slab),并自行管理生命周期 - 可通过
nginx -t -v或添加ngx_log_debug日志观察 pool 分配行为,但生产环境慎用 debug 日志
本质上,proxy 模块的“内存回收”是被动、批量、基于请求边界的。理解这一点,就能避开常见误用,比如试图在 handler 中 ngx_pfree 某个 header 字符串——这不仅无效,还可能破坏 pool 内部结构。










