5月27日 21:52

Nginx 的事件驱动模型是什么?如何实现高并发?

答案

Nginx 采用事件驱动 + 非阻塞 I/O 模型,核心是 Master-Worker 进程架构 + epoll 事件循环。每个 Worker 进程单线程运行一个事件循环,通过 epoll 同时监听数千个连接的读写事件,事件就绪时回调处理,I/O 等待期间不阻塞进程,从而用少量进程支撑数万并发连接。

事件驱动核心机制

epoll 的工作方式:内核维护一个就绪队列,只有活跃连接才会触发事件通知,时间复杂度 O(1)。与传统 select/poll 的 O(n) 轮询不同,epoll 不受 FD 数量影响——这正是 Nginx 解决 C10K 问题的根基。

事件循环流程

shell
Worker 进程启动 → 注册监听 FD 到 epoll → epoll_wait 阻塞等待事件 → 事件就绪返回 → 回调处理(accept/read/write) → 继续 epoll_wait

连接状态机:每个连接在 Worker 内部以状态机方式管理,经历 等待读 → 处理请求 → 等待写 → 发送响应 → 等待新请求(keepalive) 的状态转换,I/O 等待时让出 CPU 给其他连接处理。

Master-Worker 进程模型

nginx
worker_processes auto; # 通常等于 CPU 核心数 worker_rlimit_nofile 65535; # 文件描述符上限 events { worker_connections 10240; # 单 Worker 最大连接数 use epoll; # Linux 选择 epoll multi_accept on; # 一次 accept 多个连接 accept_mutex off; # 高并发下关闭,减少锁争用 }
  • Master:管理 Worker 生命周期,加载配置,不处理业务请求
  • Worker:各自独立运行事件循环,互不干扰,进程隔离保证稳定性
  • 理论并发worker_processes × worker_connections,4 Worker × 10240 = 40960 并发

与 Apache 的本质区别

对比维度NginxApache (prefork)
模型事件驱动,非阻塞每连接一个进程,阻塞
内存10 连接 vs 10 连点约 2MB10 连接约 200MB
C10K原生支持受限于进程数
上下文切换极少频繁

高并发调优关键参数

  1. worker_processes:设为 auto 或 CPU 核心数
  2. worker_connections:根据内存调整,通常 10240-65535
  3. accept_mutex:高并发下关闭(off),低并发开启防惊群
  4. 系统级fs.file-maxnet.core.somaxconntcp_tw_reuse

追问

  • epoll 的 LT 和 ET 模式有什么区别?Nginx 默认用哪个? — LT 水平触发会重复通知,ET 边沿触发只通知一次,Nginx 默认 LT,配合非阻塞 I/O 确保数据读完
  • 为什么 Worker 单线程还能处理上万连接? — 因为 99% 时间连接在等 I/O,事件驱动只在 I/O 就绪时才占用 CPU
  • accept_mutex 是什么?什么时候该关? — 惊群控制锁,防止所有 Worker 同时争抢新连接。连接数远大于 Worker 数时关闭可提升吞吐
标签:Nginx