nginx 域名静态解析缓存导致请求持续打到旧 ip,引发 502/超时;需检查 error.log 中 upstream 固定旧 ip 日志、验证 nslookup 结果与日志 ip 是否一致、确认 resolver 配置在 upstream 或 http 块内且 server 含 resolve 参数、valid 时间合理,并通过 reload 或变量 proxy_pass + resolver 动态解析根治。

这类故障表现为:后端服务已扩容或 IP 变更,Nginx 仍持续将请求打到旧地址,部分节点 502/超时,但直接 curl 域名又正常——本质是 Nginx 对域名做了静态解析并长期缓存,导致轮询逻辑“卡死”在旧 IP 列表上。
看日志确认是否命中 DNS 缓存固化
打开 /var/log/nginx/error.log,搜索以下线索:
-
upstream timed out 或 Connection refused,且 upstream 字段显示固定旧 IP(如
http://10.10.10.114:8080/),而非域名;说明 Nginx 早已把域名解析成该 IP 并缓存,后续所有请求都复用这个地址 - host not found in upstream 出现在 reload 阶段,说明初始解析就失败,后续即使 DNS 已修复也不会重试——这不是缓存问题,而是配置加载期硬伤
- 没有 resolver timeout 或 getaddrinfo() failed,反而说明解析成功过一次,之后就再没更新——这是缓存固化的典型特征
验证当前实际解析结果是否已变更
别只信本地 nslookup,要模拟 Nginx 的解析行为:
- 在 Nginx 所在机器执行:
nslookup your-backend-domain 8.8.8.8,确认公共 DNS 已返回新 IP - 如果用容器/K8s,进 Pod 查
/etc/resolv.conf,重点看search域是否完整(例如短域名redis必须补全为redis.default.svc.cluster.local) - 对比 Nginx 日志里记录的旧 IP 和当前 nslookup 结果,若不一致,基本锁定是缓存未刷新
检查 resolver 是否真正生效于轮询上下文
upstream 块中的轮询依赖 resolver 动态能力,但容易配置失效:
- 确保
resolver指令写在upstream块内部,或至少与之同级(如写在 http 块内);仅写在 server/location 中对 upstream 无效 - 每个
server行必须带resolve参数,例如:server api-v1.example.com resolve;,否则仍走静态解析 - 检查
valid=时间是否合理(建议 10–30 秒),太长会延迟感知变更,太短会加重 DNS 查询压力 - 确认 Nginx 版本 ≥ 1.17.5(
resolve参数支持更稳定),旧版本可能忽略 valid 设置
临时验证与根治路径
先快速止血,再推进长期方案:
- 立即
nginx -s reload强制刷新缓存——最简单有效,但不可持续 - 临时改用 IP 地址代理(如
proxy_pass http://10.10.10.200:8080)验证是否纯 DNS 问题 - 生产环境推荐:改用变量 + resolver 方式(
set $upstream "api.example.com"; proxy_pass http://$upstream;),resolver 写在 location 内,配合valid=20s,确保每次请求都可重解析 - 若需负载均衡能力,启用
upstream+zone+resolve组合,并配proxy_next_upstream error timeout实现自动剔除不可达节点











