accept_mutex不是负载均衡开关,而是防惊群协调机制;现代Nginx(1.9.1+)默认开启,仅在正确启用reuseport时自动失效,否则关闭将导致所有worker被批量唤醒、频繁返回EAGAIN,加剧上下文切换与CPU开销。

在多核环境下,accept_mutex 不是“负载均衡开关”,也不负责实现连接数的绝对均匀分配;它本质是防惊群的协调机制,现代 Nginx(1.9.1+)默认开启且仍有必要——除非你已正确启用并验证了 reuseport。
它不均衡负载,但防止更糟的情况
accept_mutex 的作用不是让每个 worker 连接数一致,而是避免所有 worker 同时被唤醒去抢 accept。若关闭它又没启用 reuseport,内核会批量唤醒全部 worker,它们几乎同时调用 accept(),绝大多数返回 EAGAIN,徒增上下文切换和 CPU 开销——这就是典型的惊群退化。
- 它只控制“谁能在当前轮次执行 accept”,不决定“连接最终分给谁”
- 连接实际分布受 multi_accept、ngx_accept_disabled、worker_connections 设置及请求模式共同影响
- 即使 accept_mutex 生效,短连接洪峰下部分 worker 仍可能暂时承接更多新连接
reuseport 是它的替代者,不是可选项
当满足以下全部条件时,Nginx 会自动禁用 accept_mutex,交由内核完成连接分发:
- 配置了 listen 80 reuseport;(或对应端口)
- Linux 内核 ≥ 3.9(支持 SO_REUSEPORT)
- Nginx 编译启用了 reuseport 支持(nginx -V | grep -i reuseport 有输出)
- 监听端口无权限限制(如容器中需设 net.ipv4.ip_unprivileged_port_start=0)
此时用 ss -tlnp | grep :80 应看到同一端口对应多个不同 PID,说明内核已在 socket 层做了分发,accept_mutex 已退出调度流程。
该开还是该关?看真实路径,不看配置行
别依赖配置文件里有没有 accept_mutex on;,而要看运行时走哪条路:
- 如果 ss 显示单 PID 监听,且 strace -e trace=accept,futex 观察到频繁 futex 等待 → accept_mutex 正在工作,应保持默认开启
- 如果 ss 显示多 PID 监听,且 strace 几乎只有 accept 调用、无 futex 等待 → reuseport 已接管,accept_mutex 是否显式配置都不起作用
- 若误关 accept_mutex 又未启用 reuseport,pidstat -w 会显示某几个 worker 的 cswch/s 异常飙升,这是惊群正在发生
配套调优不能少
即便 accept_mutex 生效,也需合理搭配才能发挥效果:
- multi_accept on;:让抢到锁的 worker 一次收完就绪队列中所有连接,减少锁争用频率
- 合理设置 worker_connections:过大易触发 ngx_accept_disabled 长期为正,导致部分 worker 主动弃权抢锁
- 避免盲目设 worker_processes auto; 在高核数机器上,过多 worker 会加剧锁竞争










