Nginx采用事件循环统一调度IO事件,每个worker进程运行永不退出的循环,通过抢锁、epoll_wait等待、事件分发与handler回调驱动执行流。

Nginx 的 IO 事件处理不是靠线性调用链推进,而是由事件循环统一调度、按需分发。执行流的控制权始终在 事件循环 手中,而非某个具体函数的返回顺序。
事件循环是唯一调度中枢
每个 worker 进程启动后,会进入一个永不退出的循环(如 ngx_process_events_and_timers),它周期性地:
- 尝试抢锁(accept mutex),避免多 worker 同时争抢新连接
- 调用底层 I/O 多路复用接口(如
epoll_wait)阻塞等待就绪事件 - 将就绪的事件(读、写、定时器、连接建立等)从内核事件队列取出并分发
- 根据事件类型和绑定的回调函数,触发对应 handler(如
ngx_event_accept或ngx_http_wait_request_handler)
事件注册决定执行入口
IO 事件是否能被调度执行,取决于它是否被正确注册进事件驱动机制:
- 监听 socket 的
read事件在ngx_event_accept中注册,用于接收新连接 - 已建立连接的 client socket 的
read事件,在ngx_http_init_connection中注册,用于读取请求头 - 写事件通常在需要发送响应、或缓冲区有数据待发时,通过
ngx_add_timer或直接调用add方法注册 - 所有注册最终都落入
ngx_event_actions_t接口的add函数(如ngx_epoll_add_event),交由 epoll 管理
回调函数构成实际执行单元
事件就绪后,Nginx 不执行通用逻辑,而是跳转到该事件预设的 handler 函数指针:
-
ev->handler在事件创建时设定(如ngx_http_init_connection中把rev->handler设为ngx_http_wait_request_handler) - handler 内部可主动触发新事件(如解析完请求后,调用
ngx_http_process_request,再注册写事件) - handler 执行完毕不“返回上层”,而是回到事件循环,等待下一轮
process_events
非阻塞与状态机协同控制流向
单个请求的完整生命周期被拆解为多个异步阶段,每个阶段由不同 handler 接管:
- 读取请求行 → 解析头部 → 接收包体 → 转发或本地处理 → 构建响应 → 发送响应 → 关闭连接
- 每个阶段完成后,显式设置下一阶段的 handler 并可能重新注册读/写事件
- 若当前操作无法立即完成(如 recv 返回
EAGAIN),handler 会直接返回,不阻塞;事件循环下次再调度该连接的读事件



















