nginx采用少量worker进程+单线程事件循环+epoll机制实现高并发:worker初始化时创建epoll实例并注册监听套接字;事件循环通过epoll_wait驱动,非阻塞处理连接各阶段;http请求被分段推进,状态由ngx_connection_t维护;模块解耦协作,资源复用降低开销。

Nginx 的异步事件驱动架构不是靠“开很多线程”来并发,而是用少量 worker 进程 + 单线程事件循环 + 操作系统级事件通知机制(如 epoll)协同工作,让每个 worker 能同时、交错地处理成千上万连接的不同阶段。
worker 进程启动:建好监听名单,不等连接先就位
每个 worker 启动时执行 ngx_event_process_init,完成三件事:
- 调用 epoll_create 创建专属的 epoll 实例
- 把监听套接字(比如 80/443 端口)以 EPOLLIN 模式注册进去
- 把所有待监控 socket 加入红黑树管理,并设为 non-blocking 模式
此时还没开始收请求,只是准备好“谁来了、什么时候来、怎么通知我”的底层能力。accept 不会卡住,recv/send 也不会阻塞。
事件循环运行:epoll_wait 驱动,有事干活、没事等或超时
worker 进入主循环,反复调用 ngx_process_events_and_timers:
- 先争抢 accept 锁(避免多 worker 同时 accept 导致惊群)
- 再调用 epoll_wait——它只在“真没活干 + 没定时器到期”时才阻塞;否则秒返回
- 拿到就绪事件列表后,遍历 rdllist,按 socket fd 找到对应连接,分发给读/写 handler
- 若无就绪事件但最小定时器已到期,就触发超时逻辑(如关闭空闲 keepalive 连接)
单连接处理:非阻塞 I/O 分段推进,不卡主线程
一个 HTTP 请求的完整生命周期被拆成多个可中断阶段:
- 收到 EPOLLIN → 调 recv 读请求头;若返回 EAGAIN,立刻退出,保持读事件注册,等下次就绪再续
- 解析完头,可能要读请求体 → 继续 recv,同样遇到 EAGAIN 就暂停,不等数据全到
- 转发给 upstream 或读取静态文件 → 发送响应时若 send 缓冲区满,只发能发的部分,注册 EPOLLOUT,等可写再发剩余
- 整个过程中,该连接的状态(如读到哪、写了多少、超时时间)都由 ngx_connection_t 结构体维护,复用不重建
模块协作与资源复用:解耦逻辑,压低开销
事件循环本身只做调度,具体业务交给模块回调:
- HTTP 模块负责解析 header、匹配 location、生成响应
- upstream 模块决定转发到哪个后端、做负载均衡
- cache 模块判断是否命中、读写缓存
- 所有连接结构预分配在连接池里,request 内存用 slab 管理,头部字段直接指针引用原始 buffer
- keepalive 复用 TCP 连接,sendfile 直接内核态传输文件,避免用户态拷贝
这种设计让 Nginx 在高并发下仍保持极低的 CPU 和内存开销。











