proxy_buffers采用链表与状态机的动态复用机制,通过busy/free双链表协同调度,按接收→发送→回收三阶段流转缓冲区,并依赖大小对齐与busy配额协同避免落盘。

proxy_buffers 的内存管理不是静态分配一块连续内存,而是基于链表与状态机的动态复用机制——它把缓冲区组织成可循环使用的“池”,由 busy 和 free 两条链表协同调度,配合 upstream 生命周期完成数据分段接收、边收边传、按需回收。
缓冲区以 chain 链表为单位组织
Nginx 不直接操作裸内存,而是将每个 buffer 封装为 ngx_buf_t 结构,并通过 ngx_chain_t 链表串联。proxy_buffers 指令(如 proxy_buffers 8 128k)实际初始化一个含 8 个 ngx_buf_t 的链表(bufs),其中首块固定用于响应头,其余 7 块供响应体使用。所有 buffer 初始挂入 free 链表,等待被上游数据填充。
三阶段流转:接收 → 发送 → 回收
缓冲区在请求生命周期中经历明确的状态迁移:
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
- 接收阶段:upstream 返回数据后,Nginx 从 free 链表取空闲 buf,填满后挂入 bufs 链表尾部;若无空闲 buf 且未超限,则触发落盘
- 发送阶段:output_filter 将 bufs 中就绪 buffer 组成新 chain,交由 write filter 下发;若下游 socket 写阻塞,该部分 buffer 不释放,转入 busy 链表等待重试
- 回收阶段:当 busy 中某 buffer 被客户端完全 ACK,ngx_http_writer 将其移回 free 链表,供后续请求复用
proxy_busy_buffers_size 是“忙区”配额,不是独立内存
该值并非额外分配内存,而是从 proxy_buffers 总量中划出的上限阈值,控制最多有多少 buffer 可处于 busy 状态。设为 512k 意味着:即使总缓存 1MB,也只允许至多 512KB 数据处于“已发未确认”状态。超出此限,Nginx 暂停读取 upstream,避免后端写阻塞;低于单块大小(如 128k),则刚填满一块就停读,极易引发 502 或卡顿。
内存复用依赖精确的大小对齐
每个 buffer 大小(size)通常匹配系统内存页(4K/8K),便于 mmap 分配与 TLB 缓存友好。若设为非页对齐值(如 100k),Nginx 可能静默退回到默认值或触发警告。macOS 对大页分配更敏感,故推荐从 16k 起步而非盲目设 128k;Linux 上则可结合典型响应块(如 32K SSE 流)设为 16 32k,提升填充效率。
不落盘的关键在于总量与忙区协同
要避免频繁写临时文件,核心不是堆大 proxy_buffers,而是让 proxy_buffers × size 覆盖常见响应体,且 proxy_busy_buffers_size 留出足够 free buffer 支持并发接收。例如 proxy_buffers 16 128k(2MB)配 proxy_busy_buffers_size 1m,意味着 1MB 可发、1MB 待填,既防上游阻塞,又保下游吞吐。再配合 proxy_max_temp_file_size 0,超限直接 502,比落盘更可控。

















