nginx proxy_pass 域名默认静态解析,需配合resolver指令和变量写法或upstream resolve实现动态dns更新。

当 Nginx 使用 proxy_pass 指向一个域名(如 CDN 回源地址 https://origin.example.com)时,它默认只在启动或重载时解析一次该域名的 IP 地址,并长期缓存这个结果——即使后端 IP 已变更,Nginx 也不会自动更新,导致回源失败或指向错误节点。
proxy_pass 域名解析的默认行为
Nginx 的 resolver 机制与 proxy_pass 是解耦的。若配置中未显式指定 resolver,且 proxy_pass 后跟的是域名而非 IP,Nginx 会依赖系统默认的 DNS 解析(通常是启动时调用 getaddrinfo()),并将结果静态缓存至 worker 进程生命周期结束。
这意味着:
- DNS 变更(如回源站切流、扩缩容、故障转移)不会被自动感知
- reload 配置不会触发重新解析(除非改动了 upstream 块或 proxy_pass 值本身)
- 长连接复用下,旧 IP 可能持续被使用数小时甚至数天
解决方法:启用动态 DNS 解析
要让 Nginx 在运行时定期刷新域名解析结果,必须同时满足两个条件:
- 在
location或upstream上下文中显式声明resolver指令(推荐使用稳定可靠的 DNS 服务器,如resolver 8.8.8.8 valid=30s;) - 将
proxy_pass改为变量形式,例如:proxy_pass https://$origin_host;,并确保$origin_host是一个运行时可变的变量(不能是字面量字符串)
这是因为 Nginx 仅对“变量中的域名”执行 resolver 解析;直接写死域名(proxy_pass https://origin.example.com;)始终走静态解析路径。
更可靠的做法:用 upstream + resolve 指令
对于 CDN 回源等关键链路,推荐使用带 resolve 参数的 upstream 块,它原生支持动态 DNS 刷新:
upstream origin_backend {
server origin.example.com:443 resolve;
keepalive 32;
}
配合:
-
resolver 1.1.1.1 valid=10s;(放在 http 或 events 块中) -
proxy_pass https://origin_backend;(注意协议需匹配,HTTPS 回源建议开启 SSL 相关配置)
这样 Nginx 会按 valid 时间间隔主动轮询 DNS,自动剔除失效 IP,并支持 SRV 记录和多 A/AAAA 记录负载均衡。
验证与排查要点
判断是否生效,可通过以下方式确认:
- 查看 Nginx error 日志中是否有
no resolver defined或host not found in upstream类报错 - 用
ss -tnp | grep :443或lsof -i :443观察实际连接的目标 IP 是否随 DNS 更新而变化 - 临时将回源域名 DNS TTL 设为 5 秒,在变更 IP 后观察 Nginx 连接是否在
valid时间内切换
注意:OpenResty 用户还可借助 resty.dns.resolver 或 lua-resty-core 实现更细粒度控制,但标准 Nginx 环境优先走 resolver + upstream resolve 组合。










