nginx 的 event loop 是基于事件驱动的单线程非阻塞 i/o 调度器,依赖 epoll/kqueue 等系统调用监听 socket 就绪事件,无用户级任务队列或 microtask 机制;所谓“排队”实为内核 accept 队列与事件就绪顺序的自然体现,通过定时器、状态机和延迟 handler 实现类异步行为,不支持自定义异步任务提交或跨请求 await。

Nginx 的 Event Loop 并不直接实现“异步任务排队”这种类似 Node.js 或 Python asyncio 的任务队列机制,它本质上是一个基于事件驱动的**单线程非阻塞 I/O 调度器**,靠操作系统底层事件通知(如 epoll、kqueue)来高效调度网络连接与读写操作,而不是运行用户级的异步任务。
核心机制:事件驱动 + 非阻塞 I/O
Nginx 主进程负责配置加载和工作进程管理,每个 worker 进程是单线程的,内部维护一个事件循环(event loop),其主干是:
- 调用 epoll_wait()(Linux)等系统调用,等待 socket 可读/可写/错误等事件就绪;
- 当事件触发时,立即执行对应 handler(如 ngx_http_process_request_line、ngx_http_read_client_request_body);
- 所有 I/O 操作都设置为 non-blocking,避免阻塞整个 worker;
- 没有独立的任务队列或 microtask/macrotask 概念,也没有类似 Promise.then() 的回调注册机制。
“排队”的真实含义:连接与请求的就绪排队
所谓“排队”,实际体现在两个层面:
- 内核队列:新连接由 listen socket 触发,内核将已完成三次握手的连接放入 accept queue;Nginx 在事件循环中调用 accept() 获取连接,再将其加入自己的连接池(ngx_connection_t 链表);
- 事件队列:数据到达时,内核将 socket 标记为可读,下次 epoll_wait() 返回该 fd;Nginx 不主动“推任务”,而是按事件就绪顺序依次处理——这看起来像排队,实则是事件就绪的自然顺序。
如何模拟“异步任务”?靠延迟处理与状态机
Nginx 本身不提供 setTimeout、setInterval 或 async/await,但可通过以下方式实现类似效果:
-
定时器(timer):使用
ngx_add_timer()注册超时事件,到期后触发回调(如关闭空闲连接、重试 upstream);底层基于红黑树管理最小堆式定时器; -
延迟读写:在 handler 中不立即处理完整请求,而是设置当前请求的状态(如
r->read_event_handler = ngx_http_block_reading),等下次事件触发再继续; - upstream 异步转发:proxy_pass 实际是分阶段完成的——先发 request header,再异步收 response header/body,各阶段通过 event handler 切换,本质是基于状态机的协作式调度。
不能做什么?明确边界
你需要知道 Nginx 的 event loop 不支持:
- 用户自定义的异步任务提交(如把一个耗时计算丢进后台队列);
- 跨请求共享的 task queue 或 await 等待任意异步结果;
- 在 handler 中 sleep() 或同步阻塞调用(会卡死整个 worker);
- 多线程任务分发(worker 是进程隔离的,无共享内存任务队列)。
如果真需要复杂异步逻辑(如调用外部 API 后组合响应),通常做法是:用 Lua(OpenResty)、JS(Nginx JavaScript module)或上游服务(如 FastCGI / gRPC)承接,让 Nginx 专注做好 I/O 调度与流量编排。











