non-blocking io 是 nginx 高并发能力的底层基石,通过事件驱动(如 epoll)使单 worker 管理上万连接,减少空等、上下文切换与内存开销,并需配合 worker_connections、sendfile、缓冲策略及异步业务逻辑才能充分发挥效能。

Non-blocking IO 是 Nginx 高并发能力的底层基石,它本身不加快单次读写速度,但能显著提升整体网络吞吐能力——关键在于让有限资源服务更多连接,减少等待与浪费。
为什么 Non-blocking IO 能提升吞吐
传统阻塞模型下,每个连接需独占一个线程或进程,数据没来时 CPU 空等;而 Nginx 的非阻塞 I/O 配合事件驱动(如 epoll),让一个 worker 进程可同时管理上万连接:
- 连接就绪才处理:内核通知数据到达后,Nginx 立即读取,不空耗 CPU 轮询
- 无上下文切换开销:避免频繁线程调度,节省 CPU 时间和内存栈空间
- 连接间互不影响:慢客户端上传、长尾响应不会卡住其他请求的读写调度
- 内存更轻量:每个连接只维护一个轻量结构体(ngx_connection_t),而非完整线程上下文
关键配置让 Non-blocking IO 发挥实效
Nginx 默认启用非阻塞 I/O,但需配合合理配置才能释放全部潜力:
- worker_processes auto;:自动匹配 CPU 核心数,充分利用多核并行能力
- worker_connections 10240;:调大单 worker 支持连接数,需同步检查系统 ulimit -n 限制
- use epoll;(Linux 下默认生效):使用高效事件机制,ET 模式已在 1.15.10+ 默认启用
- client_header_timeout 15s; 和 client_body_timeout 60s;:及时释放无效连接,避免占用事件槽位
缓冲区策略协同 Non-blocking IO 提升效率
非阻塞读写必须搭配合理的缓冲机制,否则容易因频繁小包拷贝或等待而抵消优势:
- 读阶段采用“试探性读取”:一次 recv() 只用当前可用缓冲空间,返回 EAGAIN 就暂停,不阻塞也不轮询
- 大请求体自动落盘:超过 client_max_body_size 或缓冲上限时,直接写入 client_body_temp_path,防止内存暴涨
- 写阶段支持零拷贝:启用 sendfile on; 后,静态文件由内核直传 socket,跳过用户态内存拷贝
- 延迟发送 + 智能触发:响应数据先入缓冲链,等缓冲满、连接可写或响应结束时再发,减少系统调用次数
容易被忽视的性能断点
即使 I/O 非阻塞,业务逻辑仍可能拖垮吞吐:
- Lua 脚本中执行 阻塞 DNS 查询 或同步文件操作,会卡住整个 worker —— 应改用 cosocket 或 resolver async
- 反向代理场景未开启 keepalive 连接复用,导致频繁 TCP 握手和 TIME_WAIT 堆积
- 未调优 tcp_nodelay 或 tcp_nopush:实时业务开 tcp_nodelay 减少延迟;高吞吐静态服务配合 sendfile 开 tcp_nopush 合并小包
- 日志写入未异步或未缓冲:access_log /path.log buffer=64k flush=5s 可降低 I/O 频次











