Nginx 的 Non-blocking IO 处理大并发关键技术

作者:袖梨 2026-07-01
Nginx高效处理大并发的核心在于非阻塞I/O与事件驱动(epoll/kqueue)、内核机制及资源管控协同:单worker可管理数万连接,socket设为非阻塞,配合事件循环分阶段异步处理请求,并通过超时与连接限制防资源耗尽。

Nginx 用非阻塞 I/O 处理大并发,核心不在“不阻塞”本身,而在于它把非阻塞和事件驱动、内核机制、资源管控三者拧成一股劲——单 worker 进程轻松撑起数万连接,慢连接也不卡主流程。

基于 epoll/kqueue 的事件多路复用

Linux 下 Nginx 默认用 epoll,FreeBSD/macOS 用 kqueue。这些内核接口能一次性监听成千上万个 socket 的状态变化(比如可读、可写、断开),不用轮询每个连接。当客户端发来数据或 TCP 握手完成,内核立刻通知 Nginx 哪个 fd 就绪,Nginx 只处理真正有事的那几个,其余连接安静挂在那里,不占 CPU、不抢调度时间片。

socket 全程设为非阻塞模式

每个新建立的连接,Nginx 都会调用 fcntl() 把其 socket 设为非阻塞。这意味着:

  • recv() 读不到数据时,立刻返回 EAGAIN/EWOULDBLOCK,而不是干等
  • send() 发不完数据(比如 TCP 窗口满)时,也立刻返回 EAGAIN,不卡住当前逻辑
  • 后续靠事件循环再次监听 EPOLLIN 或 EPOLLOUT,等就绪再继续操作

连接生命周期由事件循环统一拆解

一个 HTTP 请求不再是一条线走到底,而是被切成多个异步阶段,每个阶段触发对应事件:

  • TCP 连接建立 → 触发 accept 事件,Nginx 接收并注册读事件
  • 客户端缓慢发请求头 → 每次 read 返回 EAGAIN 后,继续监听该 socket 的 EPOLLIN
  • 转发请求给后端(如 upstream)→ 当前连接挂起,worker 去处理其他就绪连接
  • 后端响应返回 → 触发读事件;尝试 send 响应 → 若又遇 EAGAIN,则注册 EPOLLOUT,等可写再续发

超时与连接数限制防止资源耗尽

非阻塞不能替代合理约束,否则慢连接仍会堆积 fd 耗尽系统资源:

  • client_header_timeout / client_body_timeout:防 Slowloris 类攻击,头部或请求体发送太慢就断连
  • send_timeout:两次 send 之间间隔太久(如客户端接收极慢),直接关闭连接
  • keepalive_timeout:空闲长连接不无限留着,及时释放 fd
  • worker_connections:每个 worker 最大并发连接数,必须配合 ulimit -n 设置,确保 epoll 能监控足够多 fd

相关文章

精彩推荐