7.1.2 事件驱动与异步非阻塞模型

Nginx 采用事件驱动与异步非阻塞模型,以少量进程处理海量并发连接。连接的读写、超时、关闭等被抽象为事件,通过事件循环调度,避免为每个连接创建线程/进程造成上下文切换与内存开销。

原理草图(事件循环与回调):

文章图片

关键机制说明:
- Worker 进程维护事件循环与队列;socket 置为 non-blocking。
- 当内核通知可读/可写时才执行 I/O;遇到上游或磁盘等待时挂起并注册回调。
- 依赖 epoll/kqueue 等高效事件模型,单 Worker 即可支撑大量连接。

安装与验证(示例以 Ubuntu 与 CentOS 为例):

# Ubuntu/Debian
sudo apt update
sudo apt install -y nginx
sudo systemctl enable --now nginx

# CentOS/RHEL
sudo yum install -y epel-release
sudo yum install -y nginx
sudo systemctl enable --now nginx

# 查看编译参数与事件模块
nginx -V 2>&1 | tr ' ' '\n' | grep -E 'with-.*poll|with-.*select|with-.*epoll'

事件模型与并发连接配置示例(/etc/nginx/nginx.conf):

worker_processes auto;

events {
    use epoll;              # 显式指定事件模型(Linux 推荐 epoll)
    worker_connections 4096;# 每个 worker 最大连接数
    multi_accept on;         # 一次尽可能多接受连接
}

http {
    # 其他配置...
}

命令与参数解释:
- worker_processes auto:按 CPU 核数自动设置 Worker 数。
- worker_connections:单 Worker 最大连接数(理论最大并发≈worker_processes * worker_connections)。
- use epoll:在 Linux 上使用 epoll 事件通知机制。
- multi_accept on:新连接集中到来时提高接收效率。

可执行演示(高并发/事件模型效果):

# 1) 启动 nginx
sudo nginx -t && sudo systemctl restart nginx

# 2) 生成并发请求(需安装 wrk)
sudo apt install -y wrk  # 或 yum install -y wrk
wrk -t4 -c1000 -d30s http://127.0.0.1/

# 预期:CPU 占用上升但连接持续可用,nginx 进程不被阻塞

连接上限计算示例(含命令):

# 查看系统最大文件描述符
ulimit -n

# 计算理论最大并发(示例:4 workers * 4096 connections = 16384)
echo "4 * 4096" | bc

解释:每个连接消耗文件描述符,ulimit -n 太小会导致连接不足。

常见排错场景与命令:
1) 连接数不足/报错 “too many open files”

# 查看 nginx 进程可用 fd 上限
cat /proc/$(pgrep -o nginx)/limits | grep "Max open files"

# 临时提高限制(当前 shell)
ulimit -n 65535

2) 事件模型未生效(非 epoll)

# 查看运行中事件模型
nginx -V 2>&1 | grep -- '--with-.*poll'
# 确保 nginx.conf events 中 use epoll 并重载
sudo nginx -s reload

3) Worker 阻塞(CPU不高但响应慢)

# 查看是否有大量 TIME_WAIT/ESTABLISHED
ss -s
# 观察 nginx 进程占用与上下文切换
pidstat -p $(pgrep -o nginx) 1

练习:
1) 将 worker_connections 从 1024 调整为 8192,使用 wrk 比较 QPS 与延迟。
2) 将 use epoll 注释掉,重载后观察 nginx -V 输出与性能差异。
3) 人为设置 ulimit -n 1024,验证高并发时的错误日志并恢复。