Nginx默认对proxy_pass中的域名仅静态解析一次,IP变更后持续502错误;需配置resolver指令(如resolver 223.5.5.5 valid=30s)并改用变量形式proxy_pass(如set $backend "api.example.com:8000"; proxy_pass http://$backend),才能实现动态DNS刷新。

当 Nginx 反向代理使用域名(如 api.example.com)作为 proxy_pass 目标时,若该域名对应的 IP 地址发生变更(例如后端服务重启、容器漂移、云服务弹性伸缩),Nginx 默认不会主动刷新 DNS 缓存——它会一直沿用首次解析得到的旧 IP,直到 worker 进程重启。此时若旧 IP 已不可达,就会持续返回 502 错误,而日志中常出现 connect() failed (111: Connection refused) 或 upstream timed out。
为什么 resolver 是关键
Nginx 的 resolver 指令用于指定 DNS 解析服务器,并配合 proxy_pass 中的变量(如 $host)实现动态、按需、可缓存的域名解析。没有它,Nginx 对硬编码域名(如 proxy_pass http://api.example.com:8000)只做一次静态解析,无法感知后续变更。
正确配置 resolver 的三步操作
以下配置适用于常规 Linux 服务器(非 Docker 内部网络):
-
在 server 或 location 块外(通常在 http 块顶部)声明 resolver:
resolver 223.5.5.5 114.114.114.114 valid=30s;
推荐使用国内公共 DNS(如阿里 DNS223.5.5.5或 114 DNS),valid=30s表示 DNS 缓存有效期为 30 秒,过期后自动重查。 -
将 proxy_pass 改为使用变量形式:
❌ 错误(静态解析):proxy_pass http://api.example.com:8000;
✅ 正确(触发动态解析):set $backend "api.example.com:8000";<br>proxy_pass http://$backend;
或更简洁地:proxy_pass http://api.example.com:8000/;(注意末尾斜杠,且确保未启用resolver的上下文里不这么写;实际推荐用set显式控制)。 -
必须搭配 proxy_set_header Host:
proxy_set_header Host api.example.com;
因为使用变量后,Nginx 不再自动设置 Host 头,而某些后端(如基于域名路由的 API 网关)依赖此头识别目标服务。
Docker 环境下的特殊处理
若 Nginx 运行在 Docker 容器中,且后端服务也在同一 Docker 网络内(如通过 Compose 启动),请不要用公网 DNS 或 localhost,而应:
- 使用 Docker 内置 DNS:在
docker run或docker-compose.yml中添加--dns 127.0.0.11(Docker daemon 内置 DNS 地址); - 配置 resolver:
resolver 127.0.0.11 valid=5s;(Docker DNS 响应快,缓存时间可设短); - proxy_pass 直接写服务名:
proxy_pass http://api:5001;(前提是 Compose 中 service 名为api),此时 Docker DNS 会实时解析其当前容器 IP。
验证与调试要点
配置完成后务必执行:
- 运行
nginx -t检查语法; - 重载配置:
nginx -s reload(避免重启进程丢失连接); - 查看错误日志:
tail -f /var/log/nginx/error.log,关注是否出现could not be resolved提示; - 手动触发 DNS 变更测试:临时修改本地
/etc/hosts指向一个假 IP,观察 30 秒后是否自动恢复(验证缓存机制生效)。











