Nginx中proxy_pass直接写域名默认静态解析,需配合resolver指令和变量(如proxy_pass $backend;)实现动态DNS更新,且resolver必须显式配置在http或server块中,valid参数控制缓存时效。

直接在 proxy_pass 中使用域名时,Nginx 默认只在启动时解析一次 IP,并长期缓存——这会导致后端服务 IP 变更(如云主机漂移、容器重建、DDNS 更新)后,Nginx 仍持续转发到旧地址,引发 502、连接超时等问题。解决核心是启用运行时动态 DNS 解析,resolver 指令正是关键入口。
必须在 http 或 server 块中显式声明 resolver
Nginx 不会自动继承系统 DNS 配置,也**不从 /etc/resolv.conf 读取**。若配置里没写 resolver,它就无法做任何运行时解析。常见错误是只在 location 里写 proxy_pass http://example.com,却漏掉全局 resolver。
- 推荐写在
http块顶层,对所有 upstream 和变量代理生效 - DNS 地址选稳定可靠的,例如:
resolver 8.8.8.8 114.114.114.114 valid=30s; -
valid=30s表示最多缓存 30 秒,过期后强制重新查询——这是实现“动态刷新”的核心参数 - 避免只写一个 DNS,防止单点故障;加上
resolver_timeout 5s;防止卡死
proxy_pass 必须配合变量或 upstream 才能触发动态解析
即使写了 resolver,如果直接写 proxy_pass http://api.example.com;,Nginx 仍可能在加载配置时静态解析并固化 IP。要真正启用运行时解析,需满足以下任一条件:
- 用
set定义变量: location / {
set $backend "http://api.example.com";
proxy_pass $backend;
} - 或使用带域名的
upstream(仅 Nginx Plus 或 Tengine 支持原生动态解析) - 普通开源 Nginx 的 upstream 域名仍是静态解析,除非搭配 Tengine 的
dynamic_resolve模块
验证是否真正生效
光看配置不够,得确认 Nginx 确实在按需查 DNS:
- 修改后 reload,检查错误日志:
tail -f /var/log/nginx/error.log,正常会有类似resolving "api.example.com"...的记录 - 主动改一下目标域名的 DNS 解析结果(比如临时指向另一个测试 IP),等待超过
valid设置的时间(如 30s 后),再发起请求,观察是否连到新 IP - 用
ss -tnp | grep :80或netstat查看 Nginx worker 进程实际连接的目标 IP,比对是否已更新
进阶:应对 DNS 不可用的容错策略
真实环境中 DNS 服务可能短暂不可达,导致 proxy_pass 失败。可叠加以下防护:
-
resolver后加ipv6=off(如无 IPv6 网络,避免额外查询拖慢响应) - 在
upstream中配max_fails=1 fail_timeout=10s,让失败节点快速摘除 - 结合
proxy_next_upstream error timeout invalid_header http_502实现自动重试 - 对关键服务,建议用 Consul、Nacos 等服务发现替代纯 DNS 依赖











