Nginx的proxy_pass写域名时仅启动/重载时静态解析一次,IP则直连不解析;要动态解析域名,必须同时配置resolver指令和变量形式的proxy_pass(如http://$backend)。

Nginx 的 proxy_pass 在配置中使用域名或 IP,其解析行为有本质区别:域名在启动时(或重载时)只解析一次,而 IP 地址直接使用、不涉及 DNS;若需动态解析域名(比如后端地址变化),必须显式启用 resolver 并配合变量使用。
域名在 proxy_pass 中默认是静态解析的
当 proxy_pass 直接写域名(如 proxy_pass http://backend.example.com;),Nginx 会在配置加载阶段(nginx -t 或 nginx -s reload 时)调用系统 DNS 解析该域名,并缓存为 IP 地址。后续所有请求都直接发往这个固定 IP,**不会重新查 DNS**,即使该域名对应的 IP 已变更,Nginx 也不会感知。
- 这是为了性能,默认关闭运行时 DNS 查询
- 若后端是 Kubernetes Service、云负载均衡器等动态 VIP,这种静态解析会导致请求失败或转发到已下线节点
- 可通过
nginx -T | grep backend查看实际生效的解析结果(需开启 debug 日志或借助 strace 观察)
IP 地址无需解析,直接建立连接
如果 proxy_pass 写的是纯 IP(如 proxy_pass http://10.1.2.3:8080;),Nginx 跳过 DNS 步骤,直接用该 IP 和端口发起 upstream 连接。这种方式稳定、无延迟,但缺乏灵活性——无法利用服务发现或 DNS 轮询能力。
- 适合后端地址长期固定、网络环境可控的场景(如私有 IDC 内网)
- 注意:IPv6 地址需用方括号包裹,例如
http://[2001:db8::1]:8080 - IP 不支持 DNS TTL 自动更新,变更仍需 reload 配置
实现动态域名解析需 resolver + 变量
要让 Nginx 在每次请求(或按 TTL 缓存)时重新解析域名,必须满足两个条件:一是配置 resolver 指令指定 DNS 服务器;二是 proxy_pass 的值必须包含变量(哪怕只是简单变量),例如 proxy_pass http://$host; 或 proxy_pass http://$backend;。
-
resolver 8.8.8.8 valid=30s;—— 设置 DNS 解析器和缓存有效期(valid 是关键) -
set $backend "api.example.com"; proxy_pass http://$backend;—— 使用变量触发运行时解析 - 不支持在
upstream块中对域名做动态解析(upstream 域名仍是静态的),动态解析仅适用于proxy_pass直接带变量的写法
常见误区与验证方法
很多人误以为加了 resolver 就能让普通域名自动刷新,其实不然。只有“resolver + 变量”组合才生效。可通过以下方式验证是否真正动态:
- 修改本地
/etc/hosts或 DNS 返回值,观察 Nginx 日志中 upstream 地址是否变化(需开启error_log ... debug;) - 用
tcpdump -i lo port 53抓包,确认 reload 后或超时后是否有新的 DNS 查询 - 避免在
proxy_pass中混用协议和变量,例如https://$host需确保 SNI 和证书匹配,否则可能握手失败










