如何让 Nginx 在 proxy_pass 时每次都重新解析 DNS(动态域名)?

Nginx 默认在启动时解析 proxy_pass 的域名并缓存。强制每次解析:用 resolver 指令指定 DNS 服务器(valid 控制缓存时长),并把后端域名放进变量再 proxy_pass $变量。本文给出完整配置与坑点。

最佳实践
如何让 Nginx 在 proxy_pass 时每次都重新解析 DNS(动态域名)?封面

核心做法:Nginx 对写死在 proxy_pass 里的域名只在启动/reload 时解析一次并缓存**。要对动态域名每次请求重新解析:①配 resolver <DNS服务器IP> valid=30s;;②把域名赋值给变量 set $backend "动态域名";,然后 proxy_pass http://$backend;。走变量的 proxy_pass 才会按 resolver 的规则运行时解析。**

完整配置

http {
    resolver 223.5.5.5 119.29.29.29 valid=30s ipv6=off;   # DNS 服务器与缓存时长

    server {
        listen 80;

        location / {
            set $backend "dynamic.example.com";
            proxy_pass http://$backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}
  • valid=30s:DNS 结果的缓存时间,按域名实际 TTL 与变更频率权衡(太短增加 DNS 压力,太长变更生效慢)
  • ipv6=off:后端只有 A 记录时加上,避免 AAAA 查询干扰

为什么必须用变量

proxy_pass http://dynamic.example.com;     # ❌ 启动时解析一次,IP 变了 Nginx 不知道
set $b "dynamic.example.com";
proxy_pass http://$b;                       # ✅ 每次请求按 resolver 规则解析

这是 Nginx 的既有行为:字面量 upstream 在配置加载期解析,变量形式才走 resolver。

配套坑点

  1. resolver 必须显式指定:Nginx 不读 /etc/resolv.conf;内网场景指向内网 DNS
  2. 解析失败时的行为:域名暂时解析不出会返回 502,要有心理准备与告警
  3. ** upstream 块场景**:upstream 里的 server 域名同样启动期解析;开源版想动态解析也得走变量路线
  4. ** DNS TTL 与 valid 取较小者生效**,两边都别设太长

适用场景

云厂商 CLB 域名(IP 会变)、容器平台动态服务名、DDNS 动态公网域名等后端 IP 不固定的反代场景。

观测云对照

DNS 解析异常纳入告警。 动态解析链路下,502 的增多可能源于 DNS 抖动;观测云对 Nginx 错误日志与 502 比率的监控,能把"后端挂了"和"解析失败"区分开(error.log 里的报错内容不同)。

常见问题(FAQ)

Q:valid 设 5s 会不会把 DNS 打爆?
A:resolver 结果在 worker 内缓存共享,QPS 不直接放大到 DNS;但内网 DNS 也建议 10s 起步。

Q:能直接用系统的 systemd-resolved 吗?
A:可以指向 127.0.0.53,但要注意容器/不同网络命名空间里该地址不可达。

Q:商业版有更优雅的方案吗?
A:NGINX Plus 的 upstream server 支持 resolve 参数,按 DNS TTL 自动更新 upstream 成员,不用变量 hack。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台