Nginx Worker 进程是单线程事件循环,通过非阻塞 I/O 和 epoll/kqueue 多路复用实现不阻塞;需规避大文件读取、代理缓冲、DNS 解析等潜在同步等待,并配合 CPU 绑定、内核支持与合理配置确保高效运行。

Nginx 的 Worker 进程本身是单线程的,事件循环就运行在其中。它不会“避免阻塞”——而是从设计上就不允许阻塞发生。真正要做的,是防止外部操作把本该非阻塞的循环拖进同步等待。
用非阻塞 I/O 和多路复用打底
每个 worker 启动时,会把监听 socket 和所有客户端 socket 设为 non-blocking 模式,并注册到 epoll(Linux)或 kqueue(BSD)。这意味着:
- accept、recv、send 等调用失败时立刻返回 EAGAIN/EWOULDBLOCK,不挂起进程
- worker 不主动轮询,只等内核通过 epoll_wait 通知“哪些 fd 就绪了”
- 一次 epoll_wait 可能触发成百上千个回调,但每个回调只做少量工作(如读一段 header),立刻交还控制权
绕开或异步化可能阻塞的环节
即使底层 I/O 非阻塞,某些操作仍会意外卡住事件循环。关键是要识别并隔离它们:
- 大文件读取:禁用 sendfile(它绕过 read 路径),启用 directio + aio threads,让内核线程池处理物理读盘
- 代理响应缓冲:设 proxy_max_temp_file_size 0,配合足够大的 proxy_buffers,避免反复落盘/删临时文件
- 上传临时写入:client_body_temp_path 必须指向独立 SSD,并加 noatime 挂载参数,减少小文件随机写抖动
- DNS 解析:resolver 必须带 valid 参数,优先走本地缓存或 systemd-resolved,禁用阻塞式 gethostbyname
绑定 CPU 并限制资源争抢
事件循环高效的前提是执行环境稳定:
- worker_processes 设为物理核心数,配合 worker_cpu_affinity 固定每个 worker 到单独核心,避免缓存失效
- accept_mutex on(默认)可防惊群;若用 reuseport,则需关闭 accept_mutex,由内核直接分发连接
- worker_connections 值不能超过 ulimit -n,否则新连接会被拒绝,看似“不阻塞”,实则丢请求
配置与运行必须匹配
光写对配置不够,还得确认底层支持是否就位:
- nginx -V 查看是否编译了 --with-file-aio(aio threads 所需)和 --with-threads(thread_pool 所需)
- Linux 内核 ≥ 5.1、文件系统为 XFS/ext4,才能稳定使用 aio threads
- 用 nginx -t 验证语法,再观察实际指标:top 看 %CPU 是否平稳、iostat 看 await 是否突增、nginx stub_status 看 Active connections 是否持续堆积


















