Nginx 中需在 http 块顶层配置 resolver 并配合变量使用 proxy_pass,才能实现后端域名 IP 的自动更新;resolver 必须带 valid 参数(如 valid=30s),proxy_pass 必须引用变量(如 $backend)而非静态域名,且需手动设置 Host 请求头。

要在 Nginx 中让后端域名随 IP 变更自动更新,光写 proxy_pass http://api.example.com; 是没用的——它只在启动时解析一次。真正起效的关键,是把 resolver 放在 http 块里,并配合变量和缓存控制。
resolver 必须放在 http 块顶层
它不能塞进 upstream、location 或 events 里,否则要么报错,要么不生效。正确写法是:
http { resolver 223.5.5.5 114.114.114.114 valid=30s; ... }- 多个 DNS 地址用空格分隔,提高容错性
-
valid=30s是核心:强制每 30 秒检查一次 DNS 是否变化,不加这个参数就等于没配 - 避免使用
127.0.0.11(Docker 内置 DNS),容器环境推荐用宿主机 DNS 或 CoreDNS ClusterIP
proxy_pass 必须走变量路径
静态写法不会触发 resolver,必须让 Nginx “看到”这是一个需要实时查 DNS 的地址:
- ✅ 正确:
set $backend "api.example.com:8000"; proxy_pass http://$backend; - ❌ 错误:
proxy_pass http://api.example.com;(启动时查一次,之后永不更新) - 协议前缀
http://不能省,写成$backend或//都无效 - Host 请求头不会自动带出,需手动补:
proxy_set_header Host api.example.com;
验证是否真正在刷新
别信 nginx -t,它只校验语法。真实效果得看运行时行为:
- 改 DNS 记录(比如把域名指向一个新 IP),等超过
valid时间(如 30 秒) - 查
error.log,出现resolving api.example.com或resolved ... to 10.20.30.40才算成功 - 如果频繁报
no resolver defined,先确认 resolver 是否在 http 块、DNS 地址能否nslookup通、UDP 53 端口是否被拦截 - 加
resolver_timeout 3s;防止单次查询卡住请求
进阶:用 upstream + resolve(Nginx ≥ 1.19.0)
需要负载均衡或健康检查时,可换更规范的方式:
- 保持 http 块已有
resolver upstream backend { server api.example.com:8080 resolve valid=20s; }- 注意:
server行必须写域名,不能写 IP;低于 1.19.0 的版本会直接忽略resolve - 仍需确保
proxy_pass http://backend;指向该 upstream











