nginx 的高并发能力源于非阻塞 i/o 与事件驱动模型(epoll/kqueue)协同工作:socket 设为 non-blocking 后,配合内核事件通知实现单 worker 处理万级连接;请求由状态机驱动,通过回调函数衔接各阶段;辅以零拷贝(sendfile)和内存池优化降低开销。

Nginx 的 Non-blocking IO(非阻塞 I/O)是其实现高并发异步通信的核心基础,但它本身不等于“异步”,而是配合事件驱动模型共同构成真正的异步非阻塞处理能力。
非阻塞 I/O 是前提,不是全部
在 Linux 下,Nginx 将 socket 设置为 non-blocking 模式:调用 read() 或 write() 时,若内核暂无数据可读或无法立即写入,系统不会挂起进程,而是立刻返回错误码 EAGAIN 或 EWOULDBLOCK。这避免了线程等待,释放 CPU 去处理其他请求。
- 单次 read/write 不会阻塞,但也不保证一次读完全部数据
- 需要反复检查(轮询)是否就绪——但 Nginx 不靠忙等,而是交给事件机制
- 仅靠 non-blocking 本身效率低,必须搭配高效事件通知才能实用
事件驱动模型(epoll/kqueue)接管就绪通知
Nginx 在 Linux 上默认使用 epoll,在 FreeBSD/macOS 上用 kqueue。这些机制让内核主动告知哪些 fd 已就绪,无需用户态轮询。
- epoll_wait() 阻塞等待多个 socket 的状态变化,但只在有事件时才返回
- 一个 worker 进程可同时监听成千上万个连接,却只在真正有读/写/错误事件时才调度处理
- 事件就绪后,Nginx 调用对应的回调函数(如 ngx_http_read_request_handler),继续执行请求逻辑
回调与状态机驱动请求生命周期
Nginx 把每个 HTTP 请求抽象为有限状态机,并通过回调函数衔接各阶段:
- 收到新连接 → 触发 accept 回调 → 分配 request 结构体
- 数据可读 → 触发 read 回调 → 解析请求头 → 状态转为 “waiting for body”
- 响应生成完毕 → 触发 write 回调 → 发送响应 → 关闭或复用连接
- 整个过程不依赖多线程或协程,全由单个 worker 的事件循环驱动
零拷贝与内存池进一步降低开销
为减少系统调用和内存分配成本,Nginx 还做了关键优化:
- 用 sendfile() 实现静态文件的零拷贝发送,避免用户态/内核态间的数据复制
- 所有请求相关的内存(buffer、headers、临时变量)从预分配的内存池中申请,避免频繁 malloc/free
- 日志写入也支持异步刷盘(通过 buffer + 定时 flush 或信号触发),不拖慢主请求流程











