Nginx upstream动态解析失效的根本原因是resolver未被正确触发:必须在http块顶层配置带valid=的resolver,且需通过变量proxy_pass或upstream中server后加resolve显式激活运行时查询,否则仍静态解析。

Upstream 中动态域名 IP 变更后请求持续失败、502 报错不断,不是 DNS 没更新,而是 Nginx 仍死锁在旧 IP 上——根本原因是 resolver 没真正“活起来”。关键不在加不加 resolver,而在它是否被正确触发、及时刷新、有效作用。
resolver 必须放在 http 块顶层,且带 valid= 参数
只写 resolver 114.114.114.114; 不够,Nginx 默认缓存永不超时。必须显式指定过期时间:
-
✅ 正确写法:
resolver 114.114.114.114 8.8.8.8 valid=30s;—— 每 30 秒强制重查 DNS -
❌ 错误写法:
upstream { resolver ... }(语法报错)或location { resolver ... }(作用域太窄,upstream 块无法继承) - 别依赖系统 DNS:Nginx 不读
/etc/resolv.conf,必须手动配;建议至少两个 DNS 地址防单点失效
Upstream 域名不会自动动态解析,必须用 resolve 或变量触发
即使 http 块已配好 resolver,只要 upstream 里写的是 server api.example.com:8080;,Nginx 仍只在启动时解析一次。要打破死锁,必须显式激活运行时查询:
-
✅ 方式一(兼容老版本):不用 upstream,改用变量 proxy_pass:
set $backend "api.example.com:8080";<br>proxy_pass http://$backend;
注意:协议头http://不能省,否则不触发 DNS 查询 -
✅ 方式二(Nginx ≥ 1.19.0):在 upstream 中启用
resolve:
upstream backend {<br> server api.example.com:8080 resolve;<br>}
并确保外层 http 块已有 resolver,还可为该域名单独设 TTL:server api.example.com:8080 resolve valid=20s; -
❌ 无效写法:
upstream { server api.example.com; }+ 全局 resolver —— 完全不生效
验证是否真跳出死锁,得看 error.log,不是 nginx -t
配置语法正确 ≠ 动态解析生效。真实效果只能靠运行时日志判断:
- 修改 DNS 记录(例如把
api.example.com指向新 IP),等待超过valid=设定的时间(如 30 秒) - 查
error.log是否出现类似日志:resolved api.example.com to 10.20.30.40✅resolving api.example.com✅
若反复出现getaddrinfo() failed或resolver not found,说明 DNS 服务器不可达或 UDP 53 被拦截 - 若日志里长期只有首次解析记录,没有后续
resolved,说明 valid 未生效或变量未被 proxy_pass 使用
HTTPS upstream 需额外透传 SNI,否则仍 502
后端是 HTTPS 域名时,Nginx 默认用 IP 连接,不发 SNI,导致证书不匹配、TLS 握手失败:
- 必须开启
proxy_ssl_server_name on;,让 Nginx 在 TLS 握手时带上原始域名 - 同时确保
proxy_set_header Host也设为对应域名,避免后端网关路由错误 - 若用 upstream + resolve,SNI 同样需要该指令配合,否则即便 IP 刷新成功,连接仍断在 TLS 层


















