Nginx对upstream域名实现运行时动态解析需满足三要素:变量触发(如set $backend "api.example.com"; proxy_pass http://$backend;)、resolver置于同级location/server块并配valid=时间、或Nginx≥1.19.0时在upstream中用server域名+resolve参数且全局已声明resolver。

要让 Nginx 对 upstream 中的域名做运行时动态解析(而非仅启动时静态解析),关键不是简单加个 resolver,而是必须满足“变量触发 + 作用域正确 + 配置兼容”三要素。直接写 proxy_pass http://api.example.com; 或在 upstream 块里写 server api.example.com;,无论有没有 resolver,都只会解析一次。
用变量 + location 内 resolver 实现最简动态解析
这是最常用、无需升级 Nginx 版本、也无需额外模块的方式:
- 必须把域名赋值给变量,再在
proxy_pass中引用该变量,例如:set $backend "api.example.com";<br>proxy_pass http://$backend;
-
resolver必须放在同一location(或server)块内,不能只写在http块顶层——Nginx 不会继承; - 加上
valid=30s控制缓存时效,避免 DNS 变更后长期不生效; - 确保 DNS 服务器可达(如
8.8.8.8或内网 CoreDNS),且防火墙放行 UDP 53 端口。
upstream 块中启用动态解析(Nginx 1.19.0+)
若需复用 upstream 的负载均衡、健康检查等能力,可配合 resolve 参数:
- 全局
resolver必须已声明(推荐放在http块); -
upstream块中每个server行必须写域名(不能写 IP),并显式添加resolve; - 支持为单个域名单独设 TTL,例如:
upstream backend {<br> resolve api.example.com valid=20s;<br> server api.example.com:8080;<br>} - 注意:此方式要求 Nginx ≥ 1.19.0,旧版本忽略
resolve仍按静态处理。
避免常见配置陷阱
很多看似合理的写法实际无法触发动态解析:
-
proxy_pass http://api.example.com;—— 字面量域名,永远静态; -
resolver写在http块,但location里没重复声明且用了变量——变量解析仍失败; - 变量赋值后,
proxy_pass却没用变量(比如写了http://api.example.com而非http://$backend); - DNS 服务器返回 NXDOMAIN(域名不存在)时,Nginx 不会自动换下一个 resolver 尝试,直接报错 502。
验证是否真正生效
别只靠 nginx -t 或 reload 日志判断:
- 修改 DNS 记录(如把域名指向新 IP),等待超过
valid时间后,观察 error log 是否出现resolved ... to xxx.xxx.xxx.xxx; - 用
strace -p $(pgrep nginx) -e trace=connect抓 worker 进程连接目标,确认 IP 是否随 DNS 更新而变化; - 临时在本地 hosts 模拟变更,或用
dig +short api.example.com @8.8.8.8确认 DNS 返回已变,再比对 Nginx 行为。











