nginx worker进程采用单线程事件驱动模型实现高并发:共享监听套接字由内核分发连接,accept后注册epoll;http请求分阶段非阻塞处理;响应通过sendfile零拷贝或upstream缓冲异步发送;全程避免阻塞操作以保障吞吐。

Nginx 的 Worker 进程不靠多线程或每请求一进程来并发,而是用单线程 + 事件驱动(如 epoll)模型,在一个进程中串行调度成千上万个连接,靠“几乎不阻塞”实现高并发响应。
Worker 进程如何接收并分发新连接
多个 Worker 进程共享监听套接字(listen socket),操作系统内核(如 Linux 的 SO_REUSEPORT 或 accept_mutex)负责将新 TCP 连接分发给某个 Worker。该 Worker 调用 accept() 获取已连接套接字(connected socket),然后立即把它注册进自己的 epoll 实例,等待后续读写事件。
HTTP 请求的分阶段非阻塞处理
每个连接上的请求不是一次性读完再处理,而是按阶段拆解、事件驱动推进:
- ngx_http_wait_request_handler:首次读事件触发,调用 recv() 尝试读取请求行;若未收全,挂起等待下次 EPOLLIN
- ngx_http_process_request_line:收到完整请求行后,解析方法、URI、HTTP 版本
- ngx_http_process_request_headers:继续读取并解析请求头,完成匹配 server/location 块
- ngx_http_process_request:执行 location 内指令链(重写、鉴权、缓存检查、代理转发等)
响应生成与发送的关键机制
响应阶段同样异步非阻塞:
- 静态文件通过 sendfile() 零拷贝直接送入内核协议栈,不经过用户态内存
- 代理响应由 upstream 模块缓冲管理,支持流式转发(proxy_buffering on)或逐块透传(off,需谨慎)
- 响应头和体分开发送;若客户端支持 Keep-Alive,连接保留在 epoll 中等待下一次读事件
- 所有 I/O 操作(recv/send/sendfile)都设为非阻塞,失败时返回 EAGAIN/EWOULDBLOCK,交由事件循环重试
避免阻塞是并发能力的前提
Worker 的高吞吐依赖于全程无同步阻塞操作:
- 禁用 proxy_buffering off 且后端响应慢时,会卡住整个 Worker 的事件循环
- 慎用 auth_request 同步子请求,应配超时并启用异步替代方案
- Lua 脚本中避免 os.execute、ngx.sleep(无协程封装)、阻塞 DNS 查询
- 磁盘日志建议开启 buffered 和 flush 参数,减少 write() 阻塞概率











