Nginx缓冲区策略核心是“按需分配、分阶段处理、避免拷贝、及时释放”:读缓冲动态分配并控制边界,写缓冲支持零拷贝与延迟发送,生命周期绑定连接状态,调优需匹配业务特征。

Nginx 在非阻塞(Non-blocking)I/O 模式下,不依赖线程或进程等待数据就绪,而是通过事件驱动(如 epoll、kqueue)高效调度连接。其缓冲区读写策略是性能和稳定性的核心,关键在于“按需分配、分阶段处理、避免拷贝、及时释放”。
读缓冲区:动态分配 + 边界控制
Nginx 为每个连接维护一个 recv buffer(默认由 client_body_buffer_size 和 client_header_buffer_size 控制),但实际读取时并非一次性填满。它采用“试探性读取”策略:
- 调用
recv()时使用当前可用缓冲区空间,返回值为实际读到的字节数(可能为 0 或 EAGAIN) - 若 HTTP 头未收全,Nginx 会扩容缓冲区(不超过
large_client_header_buffers限制),但不会盲目增长 - 遇到超大请求体(如上传文件),自动切换至临时文件(
client_body_temp_path),避免内存耗尽
写缓冲区:延迟发送 + 零拷贝优化
响应数据写入 socket 前,先经过 Nginx 的 send buffer(由 output_buffers 和 sendfile 等指令影响):
- 启用
sendfile on时,静态文件直接由内核在磁盘与 socket 间传输,绕过用户态缓冲,减少内存拷贝 - 禁用 sendfile 后,数据先进入内存缓冲区;当缓冲区满、连接可写、或显式调用
ngx_http_send_special(r, NGX_HTTP_LAST)时才尝试send() - 若
send()返回 EAGAIN,Nginx 将当前连接加入 write event 队列,等待下次可写事件再续发
缓冲区生命周期:与连接状态强绑定
Nginx 不为每个请求单独分配长期缓冲区,而是复用连接级结构体(ngx_connection_t)中的缓冲区字段:
- 读缓冲区(
recvbuf)在连接建立后初始化,随连接关闭而释放;长连接中会重置指针、清空已处理数据,但保留底层数组复用 - 写缓冲区(
sendbuf)通常指向 response body chain 或 file buffer,生命周期由 request 结构管理;响应结束时自动清理链表节点 - 所有缓冲区操作均在事件回调(如
ngx_http_process_request_line、ngx_http_writer)中完成,不跨事件循环持有锁或阻塞资源
调优建议:匹配业务特征
缓冲区策略不是越大越好,需结合典型请求大小、并发连接数和系统内存权衡:
- API 服务(小包高频):适当减小
client_header_buffer_size(如 1k),增大worker_connections,降低单连接内存占用 - 文件下载/上传服务:开启
sendfile和aio threads,设置合理的directio 4m触发条件,让大文件走内核零拷贝路径 - 代理场景:注意
proxy_buffer_size(存响应头)与proxy_buffers(存响应体)分离配置,防止上游响应头过大导致截断










