nginx 的 event loop 本质是基于操作系统 i/o 多路复用(如 epoll/kqueue)的内核通知机制,配合非阻塞 socket、单线程 worker 进程模型及集成超时管理的事件驱动架构。

Nginx 的 Event Loop 并不依赖传统意义上的“事件循环”(如 Node.js 那样用单线程 JS 引擎跑一个 while 循环),而是基于操作系统提供的高效 I/O 多路复用机制,配合进程/线程模型,实现真正轻量、非阻塞的事件通知。
核心:用系统级 I/O 多路复用替代轮询
Nginx 在启动时根据运行平台自动选择最优的事件驱动模块(如 Linux 用 epoll,FreeBSD/macOS 用 kqueue,旧系统 fallback 到 select/poll)。这些机制本身是内核提供的非阻塞通知能力——Nginx 调用一次 epoll_wait(),内核会在有 socket 可读/可写/出错时才返回,不占用 CPU 空转。
- 没有“自己实现一个 loop 去不断检查 fd”,而是把监听权交给内核,等内核“叫醒”
- 每个 worker 进程独立调用
epoll_wait(),阻塞在内核态,不消耗用户态 CPU - 一旦返回,就批量处理就绪事件(比如多个 HTTP 请求同时到达),避免频繁系统调用开销
非阻塞 socket + 回调驱动的请求生命周期
Nginx 所有 socket 都设为 O_NONBLOCK。这意味着:
– accept() 不会卡住,没连接时立即返回 -1 + EAGAIN;
– recv()/send() 也一样:数据未就绪或发送缓冲区满,就立刻返回错误,而不是等。
- 每次 I/O 操作都只做“当前能做的那一小步”(例如读到多少字节、写出去多少)
- 剩余工作(如继续读请求体、写响应头)注册到 event loop,等下次该 fd 就绪再接着干
- 整个 HTTP 请求处理被拆成多个状态机阶段(read header → parse → read body → generate response → send),每阶段由事件触发推进
Worker 进程模型让事件调度更可控
Nginx 默认用多进程(非多线程),每个 worker 是单线程、单 event loop。这带来两个关键好处:
- 避免线程上下文切换和锁竞争,事件处理逻辑不用考虑并发修改共享状态
- 每个 worker 的 event loop 完全独立:一个 worker 卡在某个慢操作(如磁盘读取)不会影响其他 worker 处理新连接
- 通过 master-worker 架构 + socket 共享(SO_REUSEPORT 或 accept mutex),连接能较均衡地分发到各 worker
定时器与超时也集成进事件框架
Nginx 把超时管理也统一到 event loop 中:所有需要超时的事件(如 read timeout、keepalive timeout)都会插入一个最小堆(红黑树实现),每次 epoll_wait() 前先算好本次最多等多久(取最近超时时间与 epoll 超时参数的较小值)。
- 这样既不漏掉超时,也不需要额外线程或信号来管理 timer
- 超时事件触发后,直接关闭连接或返回 408,整个流程仍在同一个 event loop 中完成











