Nginx基于事件驱动实现高效异步I/O,核心是“注册+回调+复用”:通过epoll零开销就绪通知、回调驱动分发、非阻塞socket、独立超时与连接/内存复用,全程无阻塞、无轮询、无额外线程。

Nginx 在事件驱动架构下处理异步 I/O 完成事件,核心不是“等结果”,而是“注册+回调+复用”——它把每次 read、write、accept、timeout 都视为可调度的就绪事件,由 epoll 统一通知、事件循环批量派发、模块轻量执行,全程不阻塞、不轮询、不新建线程。
就绪通知:epoll_wait 零开销等待
每个 worker 进程只运行一个事件循环,调用 epoll_wait() 挂起等待内核通知。内核通过红黑树+就绪链表,在 socket 状态变化(如数据到达、发送缓冲区空、连接关闭)时立即插入就绪队列。Nginx 不轮询 fd,也不反复 syscalls,一次 epoll_wait 可返回数百甚至上千个就绪事件,时间复杂度接近 O(1)。
- 避免 select/poll 的 O(n) 扫描和 fd 集拷贝开销
- 超时参数由红黑树顶端最小超时值动态传入,精度高且无需额外线程
- EPOLLIN/EPOLLOUT/EPOLLERR 分类触发,写事件仅在 send 缓冲区有空间时才激活
事件分发:回调驱动,解耦业务与调度
事件循环拿到就绪列表后,不自行处理数据,而是按事件类型调用对应模块注册的回调函数。HTTP 解析、upstream 转发、日志写入等均由各自模块实现,event 模块只做分发,保持核心极简。
- recv() 返回 EAGAIN 后,不再重试,直接转向下一个就绪连接
- send() 写不完的数据留在 connection->buffer 中,并重新注册 EPOLLOUT 事件
- header 解析走内存指针偏移,不 malloc;body 大于阈值则走临时文件或流式转发
完成保障:非阻塞 + 超时 + 复用三位一体
异步 I/O 的“完成”不是指数据彻底落盘或客户端收完,而是指当前阶段具备继续推进的条件。Nginx 用三重机制确保每个环节不卡死:
- 非阻塞 socket:所有 I/O 系统调用(accept/recv/send)均设为 non-blocking,失败立即返回,绝不等待
- 独立超时控制:client_header_timeout、proxy_read_timeout 等分别计时,一个慢请求不影响其他连接
- 连接与内存复用:keepalive 复用 TCP 连接;ngx_pool_t 按请求生命周期分配释放,无 malloc 碎片
规避隐性同步瓶颈
真正的异步完成,依赖上下游全链路配合。哪怕 event 层再高效,一处同步操作也会拖垮整个 worker:
- access_log 必须启用 buffered 或异步日志模块,否则 write() 阻塞事件循环
- SSL 握手启用 ssl_session_cache,避免重复加解密耗时
- Lua 脚本禁用同步 http.request(),改用 cosocket 或将逻辑后移至 upstream
- proxy_buffering 开启后,后端响应可异步攒批,缓解 slow backend 对 client 的影响



















