nginx高并发能力源于非阻塞io、事件驱动(epoll/kqueue)与状态机三者协同:单worker进程以o_nonblock方式同时监控数万连接,仅在就绪事件触发时处理,避免阻塞等待和线程开销,配合细粒度超时控制保障资源高效复用。

Non-blocking IO 是 Nginx 高并发能力的底层支柱,它不靠堆线程、不靠等数据,而是让单个 worker 进程“同时盯住”数万连接,只在真正有事时出手——这才是并发响应水平跃升的关键。
非阻塞调用:系统调用立刻返回,绝不卡住
所有 socket 默认设为 O_NONBLOCK。调用 recv() 或 send() 时,哪怕内核缓冲区空或 TCP 窗口满,也不会挂起进程,而是立即返回 EAGAIN 或 EWOULDBLOCK。此时 worker 进程毫秒级转向下一个就绪事件,CPU 不空转、不浪费调度时间片。
- 每个 I/O 操作都带错误判断,只处理“可读/可写”状态
- 避免传统阻塞模型中“一人一连接、一连一卡死”的资源锁死
- 连接数上升时,内存与上下文切换开销几乎不变
事件驱动协同:epoll/kqueue 告诉你“谁 ready 了”
非阻塞本身不是银弹,必须搭配高效事件通知机制。Linux 下默认使用 epoll(边缘触发 ET 模式),它由内核维护就绪队列,O(1) 时间复杂度批量通知哪些 fd 可操作。
- worker 进程调用
epoll_wait(),挂起等待——但仅在有事件时被唤醒 - 一次唤醒可能带回数百个就绪连接,逐个推进其状态机(如从“读请求头”到“发响应体”)
- 未就绪的连接静静留在 epoll 表中,不占 CPU、不耗栈空间、不触发调度
状态机驱动:一个连接一个进度条
Nginx 不为连接分配线程,而是用轻量结构 ngx_connection_t 记录每个连接当前所处阶段,比如:NGX_HTTP_READING_REQUEST、NGX_HTTP_SENDING_RESPONSE。
- 收到 EPOLLIN 通知 → 检查状态,若在读请求阶段,则尝试
recv();若返回 EAGAIN,继续监听,不中断其他任务 - 后端响应就绪 → 状态切为“待发送”,注册 EPOLLOUT;发送缓冲区腾出空间后再次触发写事件
- 慢连接传数据慢?它只是状态卡在“读 body 中”,不影响其余 9999 个连接正常流转
超时与限制:防止非阻塞变成“无限挂起”
非阻塞 + 事件驱动 ≠ 永久容忍异常连接。Nginx 通过细粒度超时控制,主动清理无进展连接,确保资源不被滞留:
-
client_header_timeout 10;:请求头 10 秒没收全,断连 -
send_timeout 60;:两次send()间隔超 60 秒,关闭连接 -
keepalive_timeout 75;:空闲长连接最多保持 75 秒 -
reset_timedout_connection on;:直接发 RST,加速内核连接回收
不复杂但容易忽略:真正让并发响应变快的,不是把单次 I/O 做得多快,而是让 worker 几乎不花时间在“等”上——Non-blocking IO + epoll + 状态机,三者咬合运转,才撑得起万级并发下的低延迟响应。











