非阻塞i/o依赖缓冲机制,nginx通过动态读缓冲(按需分配、超限落盘)、链式写缓冲(零拷贝优先、遇阻即退)及合理配置(如header/body大小、超时协同)实现高性能与资源可控。

非阻塞 I/O 本身不决定缓冲怎么用,但它的运行逻辑完全依赖缓冲机制配合——没有合理的缓冲策略,非阻塞就容易变成“高频小包拷贝+频繁系统调用”,反而拖慢性能。
读缓冲:按需分配、动态扩容、超限落盘
Nginx 不为每个连接预分配大块内存,而是在事件回调中动态申请:
- HTTP 请求头默认用 client_header_buffer_size(通常 1k),未收全时可扩容至 large_client_header_buffers 指定的上限;超出即返回 400,不 OOM
- 请求体(如 POST 数据)先存入 client_body_buffer_size(默认 8k);超过该值且未达 client_max_body_size,自动写入 client_body_temp_path 的临时文件
- 连接关闭后,整个请求内存池(
ngx_pool_t)整块重置,无 malloc/free 开销,也无泄漏风险
写缓冲:链式管理、零拷贝优先、遇阻即退
响应数据不是一股脑发出去,而是分阶段调度:
- 启用 sendfile on 时,静态文件由内核直接从 page cache 推送至 socket,跳过用户态内存拷贝,一次系统调用完成传输
- 普通响应走输出链(
r->out),每个ngx_buf_t标记是否为 chunk 结尾(last_buf=1),支持断点续传 - 调用
send()返回 EAGAIN 时,Nginx 把连接加入写事件队列,等 epoll 通知“可写”再继续,不空转 CPU
缓冲配置不当会直接抵消非阻塞优势
盲目调大 buffer 不提升吞吐,反而带来延迟和资源浪费:
- API 类服务(JSON 小请求):保持默认 client_header_buffer_size 1k 和 client_body_buffer_size 8k 即可,过大易造成内存闲置与首字节延迟升高
- 文件上传场景:适当增大 client_body_buffer_size(如 32k),并确认 client_max_body_size 和磁盘空间匹配,避免频繁落盘影响 IO 性能
- 反向代理动态内容:需确保 proxy_buffer_size ≥ 后端响应 header 大小(建议 ≥12k),否则 header 被截断或强制落盘,引发解析错误
缓冲与超时协同,防止慢速攻击耗尽资源
非阻塞让连接不卡住,但恶意客户端缓慢发包仍可长期占用事件槽位:
- client_header_timeout(默认 60s)限制 header 接收窗口,超时即关闭连接
- client_body_timeout(默认 60s)控制请求体接收节奏,防慢速 POST 占用内存池
- 两者共同保障每个请求级内存池存活时间可控,避免高并发下因长连接堆积导致 fd 或内存耗尽











