nginx upstream 域名动态解析需满足三条件:resolver 必须置于 http/server 顶层、带 valid= 缓存时效(如 valid=20s)、通过变量 proxy_pass 或 server resolve 显式触发运行时查询,缺一不可。

要让 Nginx 对 upstream 域名真正实现运行时动态解析,防止后端 IP 变更后持续 502、请求打到旧地址,关键不是加个 resolver 就完事,而是让它“活起来”——即每次请求或按 TTL 主动刷新 DNS 结果。本地 resolver 配置必须满足三个硬性条件:位置正确、带缓存时效、有触发机制。
resolver 必须放在 http 或 server 块顶层
不能写在 upstream、location 或 events 块里,否则 Nginx 启动会报错,或日志反复提示 no resolver defined。推荐统一放在 http 块中,全局生效:
- ✅ 正确示例:
http {<br> resolver 127.0.0.1:53 valid=20s;<br> # 其他 server/upstream 配置<br>} - ❌ 错误写法:
把resolver放进upstream {}或某个location内 —— 作用域失效,upstream 块完全无法继承 - 本地 DNS(如 CoreDNS、dnsmasq、Consul DNS)建议监听
127.0.0.1:53或内网地址,避免走公网延迟和不稳定
valid= 参数是动态生效的核心
没有 valid=,Nginx 默认缓存永不超时,等于静态解析。这个值决定了 DNS 缓存多久后强制重查,直接关系故障恢复时间:
- 设为
valid=20s:IP 变更后最多 20 秒内自动切到新地址 - 设为
valid=5s:适合服务发现高频变更场景(如 Kubernetes Service DNS),但需确保本地 DNS 响应快、不丢包 - 可叠加
resolver_timeout 2s;防止 DNS 查询阻塞 worker 进程
必须用变量或 resolve 显式触发查询
即使 http 块已配好 resolver,只要 upstream 写的是 server api.example.com;,Nginx 仍只启动时查一次。要打破死锁,必须显式激活运行时解析:
- 方式一(兼容所有版本):用变量 +
proxy_passset $backend "api.example.com:8080";<br>proxy_pass http://$backend;
⚠️ 注意:http://协议头不能省,否则不触发 DNS 查询 - 方式二(Nginx ≥ 1.19.0):upstream 中启用
resolveupstream backend {<br> server api.example.com:8080 resolve valid=20s;<br>}
server 行必须写域名,不能写 IP;且外层http块已声明 resolver
验证是否真正在动态更新
别信 nginx -t,它只校验语法。真实效果看运行时行为:
- 修改本地 DNS 记录(比如把
api.example.com指向新 IP) - 等待超过
valid=设定的时间(如 20 秒) - 检查
error.log是否出现:resolved api.example.com to 10.20.30.40resolving api.example.com... - 若长期只有首次解析日志,说明变量没被
proxy_pass引用,或valid未生效











