nginx 的事件循环是基于 epoll 等 i/o 多路复用机制的事件驱动模型,通过非阻塞 i/o、连接池、状态机复用和内核就绪通知协同实现高并发低延迟。

Nginx 的事件循环(Event Loop)本身并不直接实现为传统意义上的“单线程 JavaScript 风格 Event Loop”,而是一个基于操作系统 I/O 多路复用机制的、由主循环驱动的事件驱动模型。它通过 epoll(Linux 下)高效地监听大量连接的就绪状态,从而避免阻塞和轮询开销,实现高并发、低延迟的网络服务。
Epoll 是 Nginx 事件驱动的核心支撑
在 Linux 系统中,Nginx 默认启用 epoll 作为事件分发器。它比传统的 select 和 poll 更高效,原因在于:
- 就绪列表驱动:epoll 不需要每次调用都遍历所有监听的 fd,而是由内核维护一个就绪链表,只返回真正有事件发生的连接;
- 边缘触发(ET)模式支持:Nginx 默认使用 ET 模式,配合非阻塞 socket,可减少重复通知,提升吞吐;
- 红黑树管理 fd:添加/删除监听 fd 的时间复杂度为 O(log n),适合动态增删海量连接。
Nginx 的 Event Loop 结构简明清晰
Nginx 主工作进程(worker process)运行一个无限循环,核心逻辑是:
- 调用
epoll_wait()阻塞等待事件(超时可控); - 收到就绪事件后,遍历返回的事件数组,对每个就绪 fd 执行对应 handler(如 accept、recv、send);
- 所有 I/O 操作均设为 非阻塞,确保单次 handler 不会卡住整个循环;
- 事件处理不跨 worker,无锁设计,靠进程隔离规避并发问题。
连接复用依赖事件与内存的协同管理
高效复用不只是 epoll 的功劳,还需配合:
-
连接池(connection pool):Nginx 预分配固定数量的
ngx_connection_t结构体,accept 到新连接时从池中获取,close 后归还,避免频繁 malloc/free; - 请求/响应状态机复用:同一个连接可处理多个 HTTP 请求(Keep-Alive),解析、过滤、输出等阶段复用 request 结构和 buffer;
- buffer 预分配与链式复用:读写 buffer 可回收再用,减少内存拷贝和分配压力。
配置与行为影响实际复用效果
epoll 的能力需通过合理配置才能充分发挥:
-
use epoll;显式启用(通常自动检测); -
worker_connections 10240;设置单 worker 最大并发连接数,应 ≤ulimit -n; -
multi_accept on;允许单次 epoll_wait 后尽可能多地 accept 新连接,减少系统调用次数; -
epoll_events 512;控制每次epoll_wait最多返回事件数,平衡响应与吞吐。
本质上,Nginx 的“高效复用”是 epoll 的内核级事件通知 + 用户态非阻塞 I/O + 内存池化 + 状态机设计共同作用的结果。它不追求单线程异步回调的编程模型,而是在稳定、可预测的前提下,把系统资源利用率推到极致。











