排查Nginx故障转移因DNS缓存未刷新导致的死循环,关键是确认Nginx是否动态重解析、是否持续打向旧IP并快速切断路径:查error.log中connect() failed或upstream timed out是否指向固定旧IP;用nginx -T和ss -tnp验证proxy_pass是否真走变量解析;确保resolver生效、upstream server含resolve关键字;临时直连新IP验证恢复,再以set变量+resolver+error_page兜底实现生产根治。

排查 Nginx 故障转移时因 DNS 缓存未刷新导致的死循环,关键不是等缓存过期或重启服务,而是确认 Nginx 是否真正按需重解析、是否把请求持续打向已下线的旧 IP,并快速切断错误路径。
看日志确认是否卡在旧 IP 上
执行 tail -f /var/log/nginx/error.log,重点找三类线索:
- 出现 connect() failed (111: Connection refused) while connecting to upstream,但后端实际已切换且新 IP 可通
- 反复出现 upstream timed out 或 Connection refused,且日志里 upstream 地址始终是同一个旧 IP(比如
http://10.20.30.40:8080),没有变化 - 缺少 resolving "xxx.com" 和后续 resolved to x.x.x.x 的日志——说明 resolver 没被触发
验证 resolver + 变量是否真生效
配置写了不等于起作用。必须交叉验证运行时行为:
- 执行 nginx -T | grep 'proxy_pass',输出中若显示的是具体 IP(如
http://172.18.0.5:8080),说明没走变量解析,仍是静态解析 - 用 ss -tnp | grep :8080 查看 Nginx worker 进程当前连接的目标地址,对比是否与你刚更新的 DNS 解析结果一致
- 手动改一次上游 DNS 指向一个新 IP,等
valid=30s过后发请求,再查 error.log 是否出现新 IP 的resolved to记录
检查故障转移逻辑是否被 DNS 卡住
死循环常发生在:健康检查失败 → 触发故障转移 → 新节点域名解析仍返回旧 IP → 请求继续失败 → 再次触发转移……形成闭环。要打断它:
- 确认 proxy_next_upstream 配置是否包含
error timeout http_502,否则即使后端不可达也不会尝试下一个 - 如果用了 upstream 块,确保每个
server行末尾加了 resolve 关键字(如server api.example.com resolve;),否则 DNS 不会随故障转移动态刷新 - 避免仅依赖
max_fails健康检查:它只对已知 IP 生效;若 DNS 缓存未更新,Nginx 根本不知道新 IP 存在
临时绕过 DNS 快速恢复,再根治
生产环境优先保通,再优化:
- 把
proxy_pass临时改成直连新后端 IP(如proxy_pass http://172.18.0.6:8080),验证业务是否立即恢复 - 确认恢复后,回退到变量方案:
set $backend "api.example.com"; proxy_pass http://$backend;,并确保resolver在同级或外层块中已声明 - 加
proxy_intercept_errors on;和error_page 502 = @refresh_dns;,在@refresh_dns中用 Lua 清 DNS 缓存(需提前配置 shared dict),实现失败即刷新


















