Nginx高效处理高并发的核心在于基于epoll/kqueue的非阻塞事件驱动模型,避免阻塞式I/O的频繁上下文切换;采用单线程事件循环+多工作进程架构,结合零拷贝、TCP优化和keepalive等内核特性协同降耗。

Nginx 之所以能高效处理大量并发连接,核心之一正是它基于非阻塞系统调用(如 epoll、kqueue)构建的事件驱动模型,从而显著减少内核态与用户态之间的频繁切换。
非阻塞 I/O 如何减少上下文切换
传统阻塞式 I/O(如 read()、accept())在数据未就绪时会让进程挂起,内核需保存现场、调度其他任务,待事件就绪再唤醒——每次阻塞/唤醒都触发一次完整的上下文切换(含寄存器、页表、栈等状态保存与恢复)。Nginx 使用 epoll_wait() 等非阻塞机制,仅在有活跃事件(如连接到达、数据可读)时才通知用户态,主线程持续运行、无需反复进出内核,单次系统调用可批量获取多个就绪事件,大幅压缩切换次数。
事件循环 + 单线程(或少量工作线程)架构
Nginx 默认采用一个主进程 + 多个工作进程(每个绑定 CPU 核心),每个工作进程内部是单线程事件循环:
- 不为每个连接创建新线程或进程,避免线程切换开销和内存占用激增
- 所有 socket 均设为
non-blocking,配合epoll_ctl()注册监听,由一次epoll_wait()统一等待多个 fd - 事件就绪后,在用户态完成 accept、recv、send 等操作,失败时立即返回(如
EAGAIN),不等待,继续处理其他事件
零拷贝与内核优化协同降低开销
减少上下文切换只是基础,Nginx 还结合多项内核特性进一步压降内核参与度:
- 使用
sendfile()实现文件传输零拷贝:数据直接从磁盘 page cache 到 socket buffer,不经过用户态内存,省去两次拷贝 + 两次上下文切换 - 启用
TCP_NOPUSH(FreeBSD)或TCP_CORK(Linux)延迟发送,合并小包,降低系统调用频次 - 连接复用(keepalive)减少重复三次握手与四次挥手带来的内核协议栈处理负担
配置与内核参数建议
要真正发挥非阻塞优势,需匹配合理的运行环境:
- 确保 Linux 内核启用
epoll(2.6+ 默认支持),Nginx 编译时检查--with-epoll_module - 调高
worker_connections(如 10240),并设置events { use epoll; worker_connections 10240; } - 增大系统级限制:
sysctl -w net.core.somaxconn=65535、fs.file-max=100000,避免因资源不足退化为轮询或阻塞行为

















