非阻塞io通过o_nonblock模式使worker能并发管理海量keep-alive连接,空闲时不占cpu,仅在epoll通知可读/可写时处理,配合keepalive_timeout与upstream keepalive实现高效复用。

非阻塞 IO 本身不“处理” keep-alive 连接,而是为 keep-alive 提供底层支撑:它让一个 worker 进程能同时盯住成千上万个空闲或活跃的 keep-alive 连接,哪个有数据就处理哪个,不因某个连接空闲而停摆。真正提升性能的关键,在于把非阻塞机制、事件驱动模型和 keep-alive 生命周期管理三者对齐。
非阻塞 IO 如何支撑 keep-alive 高效复用
keep-alive 连接在空闲时仍占用 socket 和内存结构(ngx_connection_t),但不会阻塞 worker。非阻塞 IO 的作用正是让这种“挂起状态”不浪费资源:
- 连接空闲时,内核不通知,Nginx 就不去碰它,CPU 去处理其他就绪请求
- 客户端发来新请求,epoll 立即触发可读事件,worker 快速拾取并解析 HTTP 头,无需等待或调度线程
- 响应写入遇 EAGAIN(如 TCP 窗口满),连接自动挂入写事件队列,等可写再续发,不卡主循环
keepalive_timeout 必须小于非阻塞连接的“健康窗口”
设太长会让大量连接长期驻留却无实际流量,挤占 worker_connections 和文件描述符;设太短又频繁重建,抵消非阻塞带来的并发优势。合理值取决于业务节奏:
- 静态资源服务(HTML/JS/CSS/图片):30–45 秒,匹配浏览器批量加载间隔
- 移动端 API:15–30 秒,避免弱网下中间设备静默断连后 Nginx 还维持着“假活跃”连接
- 高频微服务调用:5–15 秒,并强制搭配 keepalive_requests 100; 防止单连接僵死
注意:client_header_timeout 和 client_body_timeout 必须 ≤ keepalive_timeout,否则连接可能因读超时提前关闭,造成“空闲未释放”的假象。
反向代理场景必须配 upstream keepalive
前端 keep-alive 再高效,若到后端仍是短连,整体吞吐瓶颈仍在建连开销。非阻塞 IO 的并发能力无法传导至上游:
- upstream 块中显式配置 keepalive 32;(建议 16–64,按后端单实例承载力 × 0.7 设置)
- location 中启用 proxy_http_version 1.1; 并清空连接头:proxy_set_header Connection '';
- 确保后端返回 Connection: keep-alive,且其 keepalive_timeout 比 Nginx 大 10–15 秒
缓冲与零拷贝策略协同减少事件延迟
非阻塞 + keep-alive 的高效率,容易被低效的 I/O 路径拖累:
- 静态文件响应启用 sendfile on; 和 tcp_nopush on;,由内核直传,跳过用户态拷贝
- 禁用 gzip、sub_filter 等会破坏响应体完整性、迫使 Nginx 回退到 read()+write() 的模块
- 小响应体(如 JSON API)开启 tcp_nodelay on;,避免 Nagle 算法引入毫秒级延迟











