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 问题的根基。
事件循环流程:
shellWorker 进程启动 → 注册监听 FD 到 epoll → epoll_wait 阻塞等待事件 → 事件就绪返回 → 回调处理(accept/read/write) → 继续 epoll_wait
连接状态机:每个连接在 Worker 内部以状态机方式管理,经历 等待读 → 处理请求 → 等待写 → 发送响应 → 等待新请求(keepalive) 的状态转换,I/O 等待时让出 CPU 给其他连接处理。
Master-Worker 进程模型
nginxworker_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 的本质区别
| 对比维度 | Nginx | Apache (prefork) |
|---|---|---|
| 模型 | 事件驱动,非阻塞 | 每连接一个进程,阻塞 |
| 内存 | 10 连接 vs 10 连点约 2MB | 10 连接约 200MB |
| C10K | 原生支持 | 受限于进程数 |
| 上下文切换 | 极少 | 频繁 |
高并发调优关键参数
- worker_processes:设为
auto或 CPU 核心数 - worker_connections:根据内存调整,通常 10240-65535
- accept_mutex:高并发下关闭(
off),低并发开启防惊群 - 系统级:
fs.file-max、net.core.somaxconn、tcp_tw_reuse
追问
- epoll 的 LT 和 ET 模式有什么区别?Nginx 默认用哪个? — LT 水平触发会重复通知,ET 边沿触发只通知一次,Nginx 默认 LT,配合非阻塞 I/O 确保数据读完
- 为什么 Worker 单线程还能处理上万连接? — 因为 99% 时间连接在等 I/O,事件驱动只在 I/O 就绪时才占用 CPU
- accept_mutex 是什么?什么时候该关? — 惊群控制锁,防止所有 Worker 同时争抢新连接。连接数远大于 Worker 数时关闭可提升吞吐