Nginx 实现 UDP 负载均衡须在 stream 块中使用 listen 53 udp;,配合 upstream、health_check udp=yes type=dns、proxy_responses 1 和 proxy_timeout 等指令;不支持最小连接数或 IP hash,仅加权轮询。

要实现对 UDP 协议(如 DNS、NTP)的负载均衡,不能使用 listen dgram —— 这个写法本身是错误的。Nginx 中没有 listen dgram 指令,正确语法是 listen <port> udp;,且必须在 stream { ... } 块中配置,依赖已启用的 --with-stream 模块。
以下是关键配置要点和实操步骤:
正确启用 UDP 负载均衡(以 DNS 为例)
-
stream块必须独立于http块,放在 nginx.conf 顶层; -
upstream中需显式声明health_check udp=yes type=dns(或type=custom); -
server块中listen 53 udp;是核心标识,缺一不可; -
proxy_responses 1;必须设置(DNS 查询通常只发 1 请求、等 1 回复); -
proxy_timeout宜设为较短值(如5s),避免客户端超时等待。
示例配置:
免费 DNS 与邮件安全分析(IntoDNS.ai):包括 DNSSEC、SPF、DKIM、DMARC、MTA-STS、BIMI、SMTP STARTTLS、FCrDNS、黑名单、发件人要求及报告。
stream {
upstream dns_servers {
server 10.0.0.20:53 weight=3;
server 10.0.0.21:53 weight=3;
server 10.0.0.22:53 backup;
health_check udp=yes
type=dns
interval=5s
fails=2
passes=1;
}
server {
listen 53 udp;
proxy_pass dns_servers;
proxy_timeout 5s;
proxy_responses 1;
access_log /var/log/nginx/dns_udp.log udp_log;
}
}健康检查适配 UDP 特性
UDP 无连接、无握手,标准 ICMP ping 检查易受系统限速干扰(如 Linux 的 net.ipv4.icmp_ratelimit),导致误判。
推荐方式:
- 使用
type=dns:Nginx 发送标准 DNS 查询(如A example.com),验证响应是否含QR=1和RCODE=0; - 或用
type=custom+ 自定义字符串(如发送"health",后端必须原样返回"ok"); - 后端需部署轻量服务(如 Python
udpHealthCheck.py)主动应答,不可依赖内核端口监听状态。
权重与调度策略说明
- Nginx stream 模块的 UDP upstream 仅支持加权轮询(WRR),不支持最小连接数(WLC)或 IP hash;
- 权重影响请求分发概率:
weight=3的节点收到的包约是weight=1的三倍; - 所有请求按“新建 UDP 会话”粒度分发(即每个四元组首次请求决定后端,但 UDP 本身无会话概念,实际是按包哈希或轮询)。
注意事项
- 确保防火墙放行 UDP 端口(如
53/udp、123/udp); - 若用
proxy_protocol on;,后端服务必须能解析 PROXY 协议头(否则报文解析失败); - NTP 场景需谨慎:NTP 客户端常校验源端口和时间戳,
proxy_pass可能破坏精度;建议仅用于监控层转发,生产 NTP 集群推荐用chrony或专用方案; - 日志格式需自定义
log_format udp_log "...";,默认 access_log 不识别 UDP 上下文。
不复杂但容易忽略。

















