Nginx 通过非阻塞 I/O 与事件驱动实现高并发:socket 设为 O_NONBLOCK 后注册至 epoll/kqueue,read/write 立即返回 EAGAIN;采用渐进式读取、磁盘暂存大请求体、sendfile 零拷贝及写事件续发机制;连接与缓冲区复用,单 worker 可承载数万并发。

Nginx 使用非阻塞 I/O 处理高频率请求,核心在于“不等、不卡、不浪费”。它不为每个请求开线程,也不让进程在读写时停住,而是靠事件驱动机制高效调度成千上万连接。
请求到达后立即注册监听,不阻塞等待
当 TCP 连接建立完成(三次握手结束),Nginx 立即将该 socket 设置为 O_NONBLOCK 模式,并将其加入 epoll(Linux)或 kqueue(BSD)事件队列。此后任何 read/write 调用都立刻返回:有数据就读走,没数据就返回 EAGAIN/EWOULDBLOCK,绝不挂起 worker 进程。
- socket 创建后调用
fcntl(fd, F_SETFL, O_NONBLOCK)开启非阻塞 - 使用
epoll_ctl(EPOLL_CTL_ADD)注册可读/可写事件 - 后续所有 I/O 操作都在事件回调中触发,而非同步等待
事件循环中分阶段处理请求头与请求体
Nginx 对每个连接采用“渐进式读取”策略,避免一次性分配大缓冲区或陷入长等待:
- 先尝试读取 HTTP 请求行和头部,用默认 client_header_buffer_size(通常 1k)
- 若头部未收全,且未超限(large_client_header_buffers),则动态扩容缓冲区
- 遇到大请求体(如文件上传),自动切换至临时磁盘文件(client_body_temp_path),防止内存耗尽
- 整个过程不阻塞其他连接,worker 继续轮询 epoll_wait 获取下一个就绪事件
响应阶段按需写入,支持零拷贝与延迟发送
响应数据不直接发到网卡,而是先经过 Nginx 缓冲层,再由事件驱动择机写出:
- 启用 sendfile on 时,静态文件由内核直接从磁盘复制到 socket,跳过用户态内存拷贝
- 禁用 sendfile 时,响应数据先进入内存缓冲区;当缓冲区满、连接可写、或显式结束响应时才调用 send()
- 若 send() 返回 EAGAIN,Nginx 将该连接加入 write 事件队列,下次 epoll_wait 触发可写事件再续发
- 写缓冲区生命周期绑定 request 结构,响应结束即清理,不长期持有资源
连接复用与缓冲区高效回收
高频场景下连接频繁新建与关闭,Nginx 通过结构复用降低开销:
- 每个 ngx_connection_t 对象在连接建立时初始化 recv/send 缓冲区指针,但底层数组可复用
- HTTP 长连接中,已处理数据指针重置、内容清空,缓冲区内存不释放,减少 malloc/free 频次
- 连接关闭时,整个 connection 结构连同缓冲区一并释放,无残留资源泄漏
- worker 进程持续运行,事件循环不中断,单进程即可承载数万并发连接


















