resolver必须在http块顶层声明且带valid=参数,否则Upstream域名仅静态解析;valid控制DNS缓存生命周期,不设则启动后永不更新;需配合变量proxy_pass或upstream resolve实现动态解析。

必须在 http 块中声明 resolver,且必须带 valid= 参数,否则 Upstream 域名仍为静态解析。
resolver 必须放在 http 块顶层,不能嵌套在 upstream 或 location 里
很多人把 resolver 写进 upstream 块或某个 location 里,Nginx 会直接忽略——它只认 http、server 或 location 作用域,但 upstream 不是合法作用域。
-
resolver放在http块最稳妥,全局生效,避免漏配 - 若只在某几个
server中用动态域名,可放server块内,但需确保所有相关location都能继承(不推荐分散配置) - 写成
resolver 127.0.0.1;很可能失败:容器/K8s 中127.0.0.1不可达,应改用宿主机 IP 或 CoreDNS ClusterIP(如10.96.0.10)
valid= 是动态刷新的关键,不设就等于没配
valid 不是可选参数,它是 Nginx 控制 DNS 缓存生命周期的唯一开关。没有它,哪怕写了 resolver,Nginx 也只在启动时查一次 DNS,后续永不更新。
-
valid=30s:适合容器/服务发现场景,IP 变更频繁时用 -
valid=5m:通用推荐值,平衡时效性与 DNS 查询压力 -
valid=1h:仅限 IP 极稳定的传统部署,但故障切换延迟高,慎用 - 注意:
valid覆盖的是 Nginx 自身缓存行为,和 DNS 服务器返回的原始 TTL 无关
Upstream 动态解析需满足两个条件之一
只配 resolver + valid 还不够,Upstream 域名要真正“动起来”,还得看怎么用:
- 方式一(兼容老版本):不用
upstream块,直接在proxy_pass里写变量,例如set $backend "api.example.com"; proxy_pass http://$backend;—— 此时 Nginx 会按valid时间自动重解析 - 方式二(Nginx ≥ 1.19.0):在
upstream块中使用resolve参数,例如upstream backend { resolve api.example.com valid=30s; server api.example.com:8080; }—— 注意server行仍必须写域名,不能写 IP - 两种方式都要求外层已声明
resolver,否则日志报no resolver defined
容易被忽略的健壮性细节
真实环境里,DNS 查询失败、超时、后端 IP 已变但连接未断,这些情况比想象中常见:
- 配置多个 DNS 服务器,用空格分隔:
resolver 114.114.114.114 8.8.8.8 valid=30s; - 加
resolver_timeout 5s;(默认 30s),防止单次查询卡住整个请求 - 搭配
proxy_next_upstream error timeout invalid_header http_502;,让失败请求自动转发到其他上游(如果用了upstream块) - HTTP/2 或长连接 keepalive 可能复用旧连接,即使 DNS 已更新,旧连接仍发往原 IP —— 这不是配置问题,是协议特性,需结合业务容忍度评估


















