accept_mutex是旧内核(如Linux 2.6–3.8)下防止惊群的核心机制,需显式开启、配合epoll与multi_accept生效,且仅在未启用reuseport时起作用。

accept_mutex 不是为旧内核“专门设计”的补丁,而是在 未启用 reuseport 的所有场景下(包括旧内核)默认起效的核心协调机制。它不依赖新内核特性,而是通过用户态轻量锁控制接入调度秩序。在旧内核(如 Linux 2.6–3.8)或无法使用 reuseport 的环境中,正确启用并配合关键参数,才能真正抑制惊群。
accept_mutex 在旧内核下的生效前提
- 必须使用
epoll或kqueue事件模型(Nginx 默认就是 epoll,无需改) - 不能配置
use poll;或use select;—— 否则accept_mutex被完全忽略 - Nginx 版本需 ≥ 1.4.x,且必须显式开启:旧版本(如 1.4.7、1.6.3)默认为
off -
listen指令中不能含reuseport(旧内核不支持,写了也无效,但可能引发静默降级问题)
正确配置方式(适用于旧内核环境)
events {
use epoll; # 显式声明,确保不退化到 poll/select
accept_mutex on; # 旧版本必须写,1.9.1+ 才默认开启
multi_accept on; # 关键搭档:一次收尽就绪连接,减少锁争抢
accept_mutex_delay 200ms; # 可选:高并发下缩短等待间隔(默认 500ms)
}⚠️ 注意:
accept_mutex_delay值不宜过小(如
必须同步检查的系统与运行时项
-
确认
worker_processes合理:- 不要设为
auto后在 32 核机器上启 32 个 worker → 锁轮转太频繁,pidstat -w会看到 cswch/s 异常飙升 - 推荐值:
worker_processes 4;或worker_processes 8;(匹配物理 CPU 插槽数或 NUMA 节点数更稳妥)
- 不要设为
-
检查
worker_connections与系统限制匹配:-
ulimit -n必须 ≥worker_processes × worker_connections - 否则
ngx_accept_disabled长期为正,部分 worker 主动放弃抢锁,加剧不均
-
-
禁用干扰模块:
- 某些老旧第三方 upstream 或 Lua 模块会覆盖
ngx_event_process_init(),导致ngx_trylock_accept_mutex()不被调用 →accept_mutex形同虚设
- 某些老旧第三方 upstream 或 Lua 模块会覆盖
如何验证它真正在旧内核下工作
不用压测,三个命令即可确认:
ss -tlnp | grep :80
→ 应只看到 一个 PID 监听:80(说明未走reuseport,正依赖accept_mutex)strace -p $(pgrep nginx | head -1) -e trace=accept,futex -s 32 2>&1 | grep futex
→ 持续输出futex(FUTEX_WAIT_PRIVATE表示进程在等锁,机制活跃pidstat -w -p $(pgrep nginx | head -n 3)
→ 各 worker 的cswch/s值应接近(差异 multi_accept off 或误用了poll
旧内核下没有 reuseport,accept_mutex 就是唯一可靠的防惊群防线。它不追求连接数绝对均衡,但能确保 CPU 不被空唤醒浪费——这才是稳定吞吐的基础。


















