ipv6only=on能减少调度损耗,因其使ipv6套接字仅处理原生ipv6流量,ipv4由独立套接字承接,实现协议路径分离、避免内核映射与用户态地址归一化开销。

直接设置 ipv6only=on 就能避免双重套接字调度损耗。Nginx 默认行为在不同版本和系统上不一致,尤其在双栈监听同一端口时,若未明确控制,可能让一个 IPv6 套接字同时处理 IPv4 映射地址(即 IPv4-mapped IPv6 addresses),导致内核层面额外的协议转换与调度开销。
为什么 ipv6only=on 能减少调度损耗
当 ipv6only=off(旧版默认)时,Linux 内核允许一个 IPv6 套接字接收 IPv4 连接(通过 ::ffff:0.0.0.0 地址映射)。Nginx 若仅配置 listen [::]:80,就可能用单个套接字服务两类流量,但实际需在用户态做协议判别、地址归一化等操作,增加 CPU 开销和延迟。
启用 ipv6only=on 后,IPv6 套接字严格只处理原生 IPv6 流量,IPv4 流量则由独立的 listen 80 套接字承接——两个协议路径完全分离,调度更直接,也利于复用 reuseport 等优化机制。
推荐的 listen 配置写法
-
基础双栈(最稳妥):显式分开写,且为 IPv6 行加上
ipv6only=on
listen 80;<br>listen [::]:80 ipv6only=on;
- HTTPS 同理:
listen 443 ssl;<br>listen [::]:443 ssl ipv6only=on;
-
避免写法:不要只写
listen [::]:80且不加ipv6only;也不要依赖ipv6only=off的“自动兼容”,它在 Windows 和部分 Linux 发行版中行为不可靠。 -
注意平台差异:Windows 下
ipv6only参数基本被忽略,所以必须坚持“分开写两行”这种显式双监听方式,不依赖参数控制。
验证是否生效
修改配置后重载 Nginx,再执行:
ss -tln | grep ':80\|:443'
正常应看到两行 LISTEN 状态:一行是 *:80(IPv4),另一行是 [::]:80(IPv6),说明已建立两个独立套接字,无共享或映射行为。
补充:何时可以省略 ipv6only=on
Nginx 1.3.12+ 在 Linux 上默认启用 ipv6only=on,所以如果你用的是较新版本且确认系统内核支持(net.ipv6.bindv6only = 1),那即使不写该参数,实际效果也等同于开启。但为跨版本、跨平台一致性,仍建议显式声明。











