nginx 默认静态缓存后端域名ip导致dns轮询变更时连接超时,须通过location内resolver+valid=15s、proxy_pass变量引用、upstream server resolve、3s connect超时、健康检查与proxy_next_upstream协同实现快速失败与切换。

后端 DNS 轮询导致 IP 频繁变更时,Nginx 代理出现瞬时连接超时,本质不是“DNS 解析慢”,而是 Nginx 默认静态缓存 IP 后,旧连接仍尝试复用已失效地址——新请求发往下线节点,或连接卡在 SYN 阶段,最终触发 upstream timed out (110: Connection timed out)。解决重点在于:让解析快失败、连接快切换、故障快绕过。
启用实时 DNS 解析并缩短缓存周期
必须打破“启动时解析一次”的默认行为,改用运行时按需解析:
- 在
location块内配置resolver,指定至少两个稳定 DNS(如resolver 114.114.114.114 8.8.8.8 valid=15s timeout=3s;),valid=15s确保每 15 秒刷新一次记录,匹配典型 DNS 轮询 TTL(通常 30–60s) - proxy_pass 必须使用变量形式,例如
set $backend "api.example.com"; proxy_pass http://$backend;;直接写死域名(proxy_pass http://api.example.com;)无法触发动态解析 - 若使用
upstream块,每个server行末尾加resolve(如server api.example.com resolve;),且resolver指令需与 upstream 同级或更外层作用域生效
设置精准的连接级超时,避免单点拖慢全局
DNS 变更窗口期必然存在短暂不一致,超时策略要“宁早断、不硬等”:
-
proxy_connect_timeout 3s:TCP 握手超时设为 3 秒,防止 SYN 重传堆积 worker 进程 -
proxy_send_timeout 15s:大请求体发送超时,避免上传中途卡住 -
proxy_read_timeout 20s:从收到响应头到收完 body 的总等待时间,比默认 60s 更激进;对报表导出等长耗时接口,单独用location /report块覆盖此值
配合健康检查与自动重试,屏蔽瞬时抖动
仅靠 DNS 更新不够,还需 Nginx 主动感知节点状态:
- 在
upstream中启用max_fails=2 fail_timeout=10s,连续两次失败即临时剔除该 IP,10 秒后自动重试 - 添加
proxy_next_upstream error timeout http_502 http_503 http_504,当连接失败或返回特定错误码时,自动转发给下一个 upstream server - 搭配
keepalive 32复用连接,减少建连开销;但注意 keepalive 连接也会受 DNS 变更影响,因此需与短valid和健康检查协同
验证与观测要点
上线后需确认机制真实生效:
- 修改 DNS 记录(如将 A 记录指向一个不可达 IP),观察 error log 是否在
valid时间后出现新解析日志(含resolving关键词),而非持续重试旧地址 - 用
ss -tn sport = :80 | grep ESTAB查看活跃连接目标 IP,确认是否随 DNS 更新变化 - 压测时监控
upstream_addr日志字段,检查失败请求是否均匀分布到多个 IP,而非集中打向某一个已下线节点











