非阻塞io不提升单次读写速度,而是通过事件驱动(如epoll)、零拷贝(sendfile)、缓冲优化及合理配置(worker_connections、keepalive等)提升并发连接处理能力与资源利用率。

非阻塞 IO 本身不加快单次读写速度,它优化的是单位时间内的连接处理数量和资源利用率。Nginx 通过把“等待”从 CPU 时间中剔除,让一个 worker 进程能同时盯住成千上万的连接,从而显著提升整体数据吞吐效率。
事件驱动让非阻塞真正落地
非阻塞 socket 只是基础,真正起效靠的是事件循环与内核通知机制的配合:
- Linux 下默认启用 epoll(1.15.10+ 自动使用边缘触发 ET 模式),内核只在 socket 真正就绪(可读/可写)时才通知 Nginx,避免轮询开销
- 一次 TCP 数据可能分片到达,Nginx 不会等整包收完,而是收到多少处理多少,处理完立刻转去响应其他就绪连接
- 新连接建立、请求头到达、响应缓冲区腾出空间……所有环节都作为事件注册进同一个循环,调度统一、无额外线程介入
读写阶段的协同优化策略
非阻塞读写必须搭配合理的缓冲与传输逻辑,否则容易因频繁小操作抵消优势:
- 读取采用“试探性 recv()”:每次只用当前可用缓冲空间,返回 EAGAIN 就暂停,不忙等也不轮询
- 大请求体自动落盘:超出 client_max_body_size 或内存缓冲上限时,直接写入 client_body_temp_path,防止 worker 内存暴涨
- 静态文件启用 sendfile on;由内核直接从 page cache 拷贝到 socket,跳过用户态内存搬运,实现零拷贝
- 响应数据先入缓冲链,等缓冲满、连接可写或响应结束再批量发出,减少系统调用次数
配置与资源协同才能释放全部潜力
非阻塞能力不是孤立存在的,它依赖底层资源分配与上层行为约束:
- worker_processes auto; 让每个 CPU 核心运行一个独立 worker,避免跨核调度抖动
- worker_connections 设为 10240 左右,需同步检查 ulimit -n 是否足够(建议 ≥ worker_processes × worker_connections)
- client_header_timeout 和 client_body_timeout 要设合理值(如 15s / 60s),及时清理无效连接,释放事件槽位
- 反向代理场景务必开启 upstream keepalive,复用后端连接,避免高频 TCP 握手和 TIME_WAIT 堆积
业务逻辑不能拖慢异步流水线
即使 I/O 层完全非阻塞,一段同步代码仍可能卡住整个 worker:
- Lua 脚本中执行阻塞 DNS 查询或同步文件读写,会中断事件循环——应改用 cosocket 或 resolver async
- 启用了 gzip 或 sub_filter 等模块时,sendfile 会自动禁用,此时需评估压缩收益是否值得牺牲零拷贝路径
- SSL 私钥运算若未启用 OpenSSL 异步引擎(如 qat),RSA 解密等操作仍会同步阻塞 worker











