Nginx通过accept_mutex锁机制避免多Worker进程争抢新连接导致的“惊群效应”;仅在使用epoll/kqueue且未启用reuseport时生效,抢锁成功者调用accept(),失败者立即处理已有连接,负载相对均衡但非严格轮询。

在 Nginx 中,Worker 进程通过 accept_mutex(Accept 锁)机制协调对新连接的争抢,避免“惊群效应”(thundering herd),提升高并发下的连接处理效率和资源利用率。
Accept 锁的作用与触发时机
当多个 Worker 进程同时监听同一个端口(如 80 或 443)时,内核会将新到达的连接事件通知所有监听该 socket 的进程。若不加控制,所有 Worker 都可能尝试调用 accept(),但只有第一个成功,其余失败并浪费 CPU。Accept 锁就是为解决这个问题而设的互斥机制。
它只在以下情况生效:
- 使用
epoll或kqueue等支持边缘触发(ET)或就绪通知的事件模型时 -
accept_mutex配置为on(默认开启) - 没有启用
reuseport(即未配置listen 80 reuseport)
Worker 如何抢占 Accept 锁
每个 Worker 在事件循环中周期性尝试获取 accept 锁(本质是共享内存中的一个原子标志位)。抢到锁的 Worker 才能调用 accept() 接收新连接;没抢到的则跳过本次 accept,继续处理已有连接或等待下一轮。
关键行为包括:
- 抢锁失败后不会阻塞,而是进入常规事件处理流程(如读写已建立连接)
- 锁的持有时间极短——仅覆盖
accept()调用本身,不是整个请求处理过程 - 每次事件循环都重新竞争,保证负载相对均衡(但非严格轮询)
accept_mutex 关闭或启用的影响
可通过 accept_mutex off; 关闭该机制(通常不建议):
- 关闭后:所有 Worker 同时尝试 accept,产生大量系统调用失败,增加上下文切换和 CPU 开销
- 开启时:减少无效系统调用,降低内核竞争,但可能略微增加新连接分配的延迟(因需等待锁)
- 现代替代方案:
reuseport更优——由内核直接分发连接到不同 Worker,无需用户态锁,推荐在 Linux 3.9+ 使用
实际配置建议
默认配置已足够合理,一般无需调整。如需优化高并发场景:
- 确认
worker_processes auto;与 CPU 核心数匹配 - 启用
reuseport(Nginx 1.9.1+):listen 80 reuseport; - 若必须禁用 accept_mutex(如调试或特殊负载),应配合
multi_accept off;避免单次唤醒过多连接 - 注意:
accept_mutex_delay可设置抢锁失败后的最小等待时间(默认 500ms),但通常保持默认即可

















