非阻塞io是nginx降低cpu开销最底层机制,通过o_nonblock避免阻塞等待、epoll/kqueue批量事件驱动减少上下文切换、单线程事件循环消除线程开销,并协同sendfile零拷贝等优化进一步节省cpu。

非阻塞 IO 是 Nginx 降低 CPU 处理开销最直接、最底层的机制,它不靠“少干活”,而是让 CPU 始终在干有用的事——把原本浪费在等待上的 cycles 全部释放出来。
避免无效挂起与唤醒带来的切换损耗
传统阻塞模型中,每个连接调用 read() 或 accept() 时,若数据未就绪,内核必须保存当前线程上下文、调度其他任务、等事件后再恢复——一次等待就触发两次上下文切换。5000 并发连接下,每秒可能产生上万次切换,CPU 大量时间花在“换人”而非“干活”。Nginx 将所有 socket 设为 O_NONBLOCK,recv() 立即返回 EAGAIN,worker 不停顿、不休眠,继续处理其他就绪事件。
批量事件驱动,大幅压缩系统调用频次
Nginx 使用 epoll_wait()(Linux)或 kqueue()(BSD/macOS)一次性监听成千上万个 fd:
- 内核只在真正有事件(可读、可写、断连)时才通知,无事件时 worker 持续运行在用户态
- 一次
epoll_wait()可返回几十甚至上百个就绪 fd,后续accept/recv/send都在用户态集中完成 - 上下文切换次数从“每连接多次”降为“每批活跃事件一次”,压测中常减少 90% 以上
配合单线程事件循环,消除线程级开销
每个 worker 进程是单线程事件循环,不为连接创建新线程:
- 没有线程创建/销毁开销,也不用管理线程栈(每个线程默认 1–8MB 内存)
- 所有回调顺序执行,无需锁、无抢占调度、无跨线程同步成本
- 连接状态完全隔离在各自 worker 内,某个慢请求(如上游延迟)不影响其他连接处理
协同优化进一步放大 CPU 节省效果
非阻塞 IO 本身只是起点,真正释放 CPU 还依赖配套设计:
-
sendfile()实现零拷贝:文件响应不经过用户态内存,省去两次数据拷贝 + 两次上下文切换 -
multi_accept on让单次 epoll 返回后尽可能多 accept 新连接,摊薄系统调用成本 - 禁用隐式阻塞操作,例如关闭
proxy_buffering(防 upstream 慢导致 worker 卡住)、避免aio threads(引入额外线程池) - 合理设置超时(
client_header_timeout、keepalive_timeout),及时释放无效连接,防止事件槽位被长期占用











