Nginx通过异步事件驱动、非阻塞I/O、单线程事件循环+多worker进程、内核协同优化(如sendfile、TCP_CORK、keepalive)及CPU亲和性绑定,大幅减少上下文切换与系统调用,实现高并发低开销。

Nginx 的异步事件驱动模型能显著减少内核上下文切换,核心在于它用“事件就绪才处理”替代了“为每个连接单独等待”,把切换频率从“每连接一次”压降到“每批事件一次”。
非阻塞 I/O 避免进程挂起
传统阻塞调用(如 read()、accept())在无数据时会让进程进入睡眠,内核必须保存当前状态、调度其他任务,等数据到达再唤醒——每次挂起+唤醒都是一次完整上下文切换。
Nginx 把所有 socket 设为 O_NONBLOCK,配合 epoll_wait()(Linux)或 kqueue(BSD/macOS),只在至少一个 fd 就绪时才返回。期间 worker 进程始终运行在用户态,不主动让出 CPU,也不反复进出内核。
-
epoll_wait()一次可监听成千上万个 socket,返回的是就绪事件列表,不是单个连接状态 - 没有数据可读时立即返回
EAGAIN,Nginx 记录状态后继续处理其他就绪事件,不卡住循环 - 连接建立、请求头读取、响应发送等都拆成小步骤,靠状态机驱动,避免长耗时阻塞
单线程事件循环 + 多 worker 进程结构
每个 worker 进程内部是单线程事件循环,不为每个连接创建新线程或进程:
- 不需要线程调度器介入,消除线程间切换开销
- 所有 socket 共享同一个 epoll 实例,系统调用次数极少
- 内存占用低(几 MB 支撑数万并发),栈空间固定,无动态分配压力
- 即使上游响应慢或客户端上传慢,Nginx 也会挂起该请求,转去处理其他就绪连接
协同内核机制进一步压缩内核参与
减少上下文切换不是孤立优化,而是和多项内核特性联动:
-
sendfile()实现零拷贝:文件内容直接从页缓存送入 socket buffer,跳过用户态内存拷贝,省掉两次上下文切换 -
TCP_NOPUSH/TCP_CORK合并小包,降低write()系统调用频次 -
keepalive复用 TCP 连接,避免频繁三次握手与四次挥手带来的协议栈开销 - 异步 DNS 解析、缓冲日志、依赖内核页缓存读静态文件,全程避开阻塞点
CPU 亲和性固化执行路径
即使事件模型高效,若 worker 进程在不同 CPU 核之间迁移,仍会触发 TLB 刷新、缓存失效和额外切换:
- 配置
worker_cpu_affinity auto或显式掩码(如0001 0010 0100 1000),让每个 worker 绑定到固定物理核 - 验证方式:
ps -eo pid,args,psr | grep 'nginx: worker'查看各进程实际运行核编号 - 结合
worker_rlimit_nofile和系统ulimit -n调整,确保文件描述符足够支撑高并发监听
不复杂但容易忽略



















