nginx 的 event loop 是由 worker 进程自主驱动的同步调度循环,基于内核事件通知机制(如 epoll/kqueue/iocp)实现“主动拉取 + 顺序执行”,通过动态注册事件 handler、单线程遍历就绪队列并同步调用回调函数来高效处理海量连接。

Nginx 的 Event Loop 不是操作系统级回调机制,而是一个由 worker 进程自主驱动的同步调度循环。它不靠多线程并发,也不依赖内核直接调用你的函数,而是通过“主动拉取 + 顺序执行”来处理海量连接。
事件触发完全由内核通知驱动
Linux 下默认使用 epoll,FreeBSD 用 kqueue,Windows 用 IOCP——这些机制让内核在 socket 状态变化时(如可读、可写、出错)主动通知 Nginx,避免了 select/poll 的遍历开销。Nginx 不轮询,只等内核说“这个 fd 就绪了”。
- 监听 socket 就绪 → 触发 accept,生成新连接
- 客户端 socket 可读 → 调用 read handler(如解析请求行)
- 客户端 socket 可写 → 调用 write handler(如发送响应体)
- 定时器到期 → 内核不参与,Nginx 自己查红黑树,把超时事件标记为就绪
事件注册发生在连接生命周期的关键节点
不是一次性全局注册,而是按需动态绑定 handler:
- worker 启动时,把监听 socket 的读事件注册进去,handler 设为 ngx_event_accept
- accept 新连接后,在 ngx_event_accept 里为该连接的读事件设 handler,比如 ngx_http_init_request
- 需要发数据时,才为写事件注册 handler(如 ngx_http_writer),并可能临时加 EPOLLOUT
- upstream 连接不立刻握手,而是把 connect 封装成写事件注册,等下一轮 epoll_wait 就绪后再执行
事件分发与回调是同步、单线程、可控的
Event Loop 主循环每次只做三件事:等事件、搬事件、调 handler。
- 调用 epoll_wait() 阻塞等待,超时时间来自定时器系统
- 把内核返回的就绪 fd 转成 ngx_event_t*,填入就绪队列
- 遍历队列,对每个事件执行 ev->handler(ev) —— 这就是你注册的函数,运行在当前 worker 的唯一上下文中
- handler 执行完,可能再注册新事件(如读完 header 后注册 body 读事件),继续推进状态机
协议处理不在 Event Loop 内判断,而在连接建立时就已确定
Event Loop 本身不识别 HTTP 或 TCP Stream,它只负责“唤醒”。真正决定怎么处理一个连接的,是连接创建时设置的 connection->read->handler:
- HTTP 模块在 ngx_http_add_listening 中设 handler 为 ngx_http_init_request
- Stream 模块在 ngx_stream_add_listening 中设 handler 为 ngx_stream_init_session
- 后续所有读写事件,都只是忠实执行这个预设的 handler











