multi_accept指令不开启“一次性接受多个新连接”,而是控制worker在单次事件循环中是否尽可能多地调用accept()取空内核已就绪连接队列;需配合epoll、accept_mutex on及足够大的内核backlog才有效。

在 Nginx 中,multi_accept 指令本身**并不开启“一次性接受多个新连接”**,它控制的是:当一个 worker 进程收到 `epoll`(或 `kqueue`/`select`)事件通知有新连接到达时,是否**尽可能多地调用 accept() 系统调用**,把当前已就绪的多个连接全部取出来,而不是只取一个就返回。
换句话说,它影响的是单次事件循环中处理已就绪连接的“贪婪程度”,不是开启某种批量连接接收模式。它的效果依赖于底层事件模型和内核行为,且仅在启用 accept_mutex 时才有明显意义。
启用 multi_accept 的正确方式
该指令必须放在 events 块中,且通常与 accept_mutex 配合使用:
events {
use epoll;
accept_mutex on; # 启用 accept 互斥锁(默认 on,但显式写出更清晰)
multi_accept on; # 关键:允许单次事件中 accept 多个连接
worker_connections 1024;
}multi_accept 起作用的前提条件
-
必须启用事件驱动模型:如
epoll(Linux)、kqueue(FreeBSD/macOS),不适用于select或poll(它们本身不支持就绪队列批量通知) -
accept_mutex 应为 on:否则多个 worker 可能同时争抢 accept,
multi_accept的收益会被竞争抵消,甚至引发负载不均 -
内核 TCP 队列中需有多个已完成三次握手的连接:即
listen()的 backlog 队列里已有多个 SYN_RECV → ESTABLISHED 的就绪连接;如果队列里只有一个,开不开multi_accept效果一样
它不能做什么?常见误解澄清
-
不是“并发 accept 多个连接”:Nginx 是单线程 accept(每个 worker 单独调用),
multi_accept只是让一次事件回调里多执行几次accept(),不涉及并行系统调用 - 不会降低延迟或绕过 TCP 握手:它不改变网络层行为,只是更高效地消费内核已完成握手的连接
- 对小流量站点几乎无感:高并发短连接场景(如 HTTP API 突发请求)下,减少事件循环次数、提升吞吐才更明显
验证是否生效(Linux 下)
可通过观察 worker 进程的系统调用行为粗略判断:
# 对某个 nginx worker 进程(PID)进行 syscall trace strace -p <worker_pid> -e trace=accept4 -f 2>&1 | grep accept4</worker_pid>
开启 multi_accept on 后,在压测期间,同一秒内可能看到连续多个 accept4(…)=>fdX 输出;而关闭时往往间隔更长、单次仅一个。











