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