非阻塞IO是Nginx高并发长连接的基石,通过epoll事件驱动管理空闲/慢连接,配合keepalive_timeout等约束防止资源耗尽。

非阻塞 IO 是 Nginx 支持长连接高并发的底层基石,它让单个 worker 进程能同时管理成千上万个空闲或慢速传输的连接,而不会因等待数据就绪而停摆。
长连接不等于“一直占用 CPU”
HTTP keep-alive 允许客户端复用 TCP 连接发多个请求,但真实场景中,连接常处于“已建立、无数据、随时可能来新请求”的空闲状态。非阻塞 IO 让 Nginx 在这种状态下不做任何轮询或等待:socket 被注册进 epoll 后,仅当有数据可读(EPOLLIN)或可写(EPOLLOUT)时才被唤醒处理。空闲连接只是 epoll 监听列表里的一个 fd,几乎不消耗 CPU 和调度资源。
慢请求不拖垮其他连接
客户端上传大文件、网络抖动、TLS 握手延迟等都会导致单次 read/write 无法立刻完成。非阻塞模式下,Nginx 遇到 EAGAIN/EWOULDBLOCK 就立即返回,把控制权交还事件循环——此时它可无缝切换去处理其他就绪连接的请求头解析、静态文件发送或 upstream 响应转发。哪怕有上千个慢传 Body 的连接,worker 进程依然响应迅速。
事件驱动串联整个长连接生命周期
一个 keep-alive 连接从建立到关闭,被拆解为多个异步阶段,每个阶段由对应事件触发:
- TCP 握手完成 → 触发 accept,注册 EPOLLIN 等待请求头
- 收到部分 header → 解析后若不完整,继续监听 EPOLLIN,不阻塞
- 请求处理完成、准备发响应 → 调用 send;若 TCP 缓冲区满,立即返回 EAGAIN,转而注册 EPOLLOUT 等待可写
- 响应发完、连接空闲 → 启动 keepalive_timeout 计时器,超时则关闭 fd
必须配合超时与连接数约束
非阻塞本身不解决资源无限堆积问题。长连接若无管控,仍会耗尽内存和文件描述符:
- keepalive_timeout 控制空闲连接存活时间,建议设为 15–60 秒,避免僵尸连接长期驻留
- client_header_timeout / client_body_timeout 防止恶意慢速攻击(如 Slowloris),对迟迟不发完 header 或 body 的连接主动断开
- worker_connections 限制单个 worker 可管理的最大连接数,需与系统 ulimit -n 匹配,确保 epoll 不溢出
- 缓冲区大小(如 client_header_buffer_size)按实际需要设定,过大反而增加延迟和内存压力


















