Nginx 的非阻塞 I/O 通过 O_NONBLOCK 标志配合 epoll/kqueue 实现高并发低延迟,结合缓冲区策略、事件驱动架构及合理调优,单 worker 进程可高效管理数万连接。

Nginx 的 Non-blocking I/O 是它能在单进程下支撑数万并发、把响应时间压到十毫秒级的关键,不是靠“更快地读”,而是靠“不空等、不错过、不浪费”。
非阻塞机制让连接不卡在等待上
传统阻塞模式下,一个连接调用 recv() 时若没数据,线程就挂起;而 Nginx 在 socket 上设了 O_NONBLOCK 标志,每次读取立即返回:有数据就读走,没数据就收到 EAGAIN 错误,马上转去处理别的就绪连接。它不轮询,也不开新线程,全靠 epoll(Linux)或 kqueue(BSD)监听成千上万个 fd 的“可读/可写”状态——哪个就绪,就处理哪个。
- 避免了线程切换开销,CPU 不花在睡眠和唤醒上
- 单 worker 进程可管理数万连接,资源占用低
- 请求来了不排队等线程,只要事件就绪就能立刻响应
缓冲区策略配合非阻塞,减少拷贝与等待
非阻塞 I/O 不是孤立工作的,它和 Nginx 的缓冲区设计深度协同:
- 读缓冲按需分配:HTTP 头未收全时动态扩容,但上限可控;超大请求体自动落盘到 client_body_temp_path,防止内存暴涨
- 写缓冲支持零拷贝:启用 sendfile on 后,静态文件由内核直接从磁盘送入 socket,跳过用户态内存拷贝
- 发送遇阻不重试:send() 返回 EAGAIN 时,Nginx 把连接加入写事件队列,等下次可写再续发,不占着 CPU 空转
事件驱动模型放大非阻塞的实际收益
Non-blocking 只是基础能力,真正让它发挥价值的是 Nginx 的事件驱动架构:
- multi_accept on:允许单次 epoll_wait() 收集多个就绪连接,批量接受,减少系统调用次数
- use epoll(Linux)或 use kqueue(macOS/BSD):比 select/poll 更高效,时间复杂度接近 O(1)
- worker_connections 和 worker_processes 匹配硬件:通常设为 CPU 核心数 × 每核支持连接数,确保事件分发不成为瓶颈
调优要避开常见误区
非阻塞本身不等于高性能,配置不当反而拖慢响应:
- 缓冲区设太大(如 client_header_buffer_size 64k)会浪费内存,且增加首次分配延迟
- keepalive_timeout 过短(如 5s)导致连接频繁重建,抵消非阻塞带来的复用优势
- 关闭 access_log 能直接减少磁盘 I/O 延迟,尤其在 QPS 过万时效果明显
- tcp_nodelay on 可减少小包延迟,但对大文件传输可能略增包数量,需按业务权衡


















