Nginx通过事件驱动的非阻塞I/O模型实现高并发,用少量worker进程轮询epoll/kqueue监听大量socket,配合超时配置防慢连接耗尽资源。

nginx 通过事件驱动的非阻塞 I/O 模型,天然规避了传统阻塞式 Web 服务器在慢连接场景下的线程/进程堆积问题。它不为每个连接分配独立线程或进程,而是用少量工作进程(worker processes)轮询监听所有活跃连接的 I/O 事件,真正实现“一个进程处理成千上万并发连接”。
非阻塞 socket + epoll/kqueue 是基础
nginx 在 Linux 上默认使用 epoll(FreeBSD/macOS 用 kqueue),这些内核机制支持高效地监控大量 socket 的读写就绪状态。socket 被设为非阻塞模式后,recv() 或 send() 调用不会卡住:若无数据可读或无法立即发送,系统立刻返回 EAGAIN 或 EWOULDBLOCK,nginx 就转去处理其他就绪事件,而不是等待。
连接生命周期由事件循环统一调度
一个 HTTP 连接从建立到关闭,全程被拆解为多个异步事件阶段:
- TCP 握手完成 → 触发 accept 事件,nginx 接收连接并注册读事件
- 客户端缓慢发请求头/体 → 每次 read 返回 EAGAIN 后,继续监听该 socket 的 EPOLLIN,不阻塞其他请求
- 响应生成中(如 proxied 到后端)→ 当前连接挂起,等待后端返回;此时 nginx 照常处理其他连接的读写
- 后端响应就绪 → 触发写事件,尝试 send;若 TCP 窗口满导致 send 阻塞(实际是非阻塞下的 EAGAIN),则注册 EPOLLOUT,等可写再续发
关键配置防止慢连接耗尽资源
非阻塞本身不能无限兜底,需配合合理超时与限制:
- client_header_timeout / client_body_timeout:控制客户端发送请求头/体的最长时间,超时即断连,防恶意慢速攻击(如 Slowloris)
- send_timeout:向客户端发送响应时,两次写操作之间的最大间隔,避免因客户端接收慢长期占用连接
- keepalive_timeout:空闲长连接保持时间,及时回收不再活跃的 socket
-
worker_connections:每个 worker 进程允许的最大并发连接数,应结合系统
ulimit -n设置,确保 epoll 能监控足够多 fd
对比阻塞模型:为什么不会“卡住”
Apache prefork 模式下,每个连接独占一个进程;若 1000 个客户端以 1 字节/秒的速度传 Body,就会锁住 1000 个进程,后续请求只能排队等待——这就是典型的慢连接堆积阻塞。
而 nginx 中,这 1000 个慢连接只是 epoll 监听列表里的 1000 个 fd。只要其中任意一个就绪(比如某客户端终于发完 header),事件循环就处理它;其余连接处于“等待就绪”状态,不消耗 CPU、不抢占调度时间片,也不阻塞其他连接的处理流程。










