Nginx 默认仅启动时静态解析后端域名,需同时配置顶层 resolver(含 valid= 参数)、proxy_pass 引用变量(如 http://$backend)或 upstream 中 server 后加 resolve(≥1.19.0),三者缺一不可,否则无法响应IP变更。

Nginx 默认只在首次建立连接时解析一次后端域名,之后长期缓存 IP 地址——这不是 bug,而是设计行为。一旦后端服务 IP 变更(如容器重建、云主机漂移、DDNS 更新),Nginx 仍会把请求发往旧地址,引发 502、超时或部分请求失败。真正解决问题,关键不是“清缓存”,而是让 Nginx 具备运行时动态 DNS 解析能力。
必须显式配置 resolver,且不能依赖系统 DNS
Nginx 不读 /etc/resolv.conf,也不自动继承系统配置。若 http 或 server 块里没写 resolver,它就完全无法做运行时解析。推荐放在 http 块顶层,全局生效:
http {
resolver 8.8.8.8 114.114.114.114 valid=30s;
resolver_timeout 5s;
}valid=30s 表示最多缓存 30 秒,过期后强制重新查 DNS;多个 DNS 地址防止单点失效;resolver_timeout 避免因 DNS 响应慢拖住 worker 进程。
proxy_pass 必须用变量,不能直接写域名
即使写了 resolver,只要 proxy_pass http://api.example.com; 这样写死,Nginx 就会在加载配置时静态解析并固化 IP。要触发动态解析,必须走变量路径:
- ✅ 正确方式(location 内):
location /api/ { set $backend "http://api.example.com:8080"; proxy_pass $backend; } - ❌ 错误方式(无论 resolver 是否存在):
location /api/ { proxy_pass http://api.example.com:8080; # 静态解析,永不更新 }
upstream 域名不支持原生动态解析upstream 块里的 server api.example.com; 启动时解析一次,后续永不刷新。若你依赖 upstream 结构(比如需要负载均衡算法或健康检查),有三个可行方案:
- 使用第三方模块
nginx-upstream-dynamic-servers,支持resolve参数(需验证 Nginx 版本兼容性) - 改用
proxy_pass + 变量模式,配合map或多个location实现路由分发 - 通过 Lua 脚本(如
resty.dns)在content_by_lua_block中手动解析并设置目标地址,灵活性最高
验证是否真正生效,别只看配置
光写对配置不够,得确认 Nginx 实际行为:
- 查错误日志:
tail -f /var/log/nginx/error.log,正常会有resolving "api.example.com"和resolved ... to x.x.x.x记录 - 看连接目标:
ss -tnp | grep :8080,观察 worker 进程连接的 IP 是否随 DNS 变更而更新 - 主动测试:临时修改该域名的 DNS 解析结果(如指向一个测试 IP),等超过
valid时间后发起请求,检查是否连到新地址 - 检查配置展开:
nginx -T | grep 'proxy_pass',如果输出的是http://1.2.3.4:8080,说明没走变量,仍是静态解析


















