resolver指令必须放在http块顶层,不能置于server或upstream内,否则报错“directive is not allowed here”;正确写法为http块内声明resolver并设valid参数,upstream中server需带端口及resolve关键字。

nginx resolver 指令必须放在 http 块里,不能写在 server 或 upstream 内部
很多人把 resolver 直接塞进 upstream 或 server 块里,结果 reload 时提示 nginx: [emerg] "resolver" directive is not allowed here。这是语法错误——resolver 只能在 http 级别生效,且必须在使用 resolve 的 upstream 之前定义。
正确写法示例:
http {
resolver 8.8.8.8 114.114.114.114 valid=30s;
resolver_timeout 5s;
upstream dynamic_api {
server api.example.com:8080 resolve;
}
server {
listen 80;
location / {
proxy_pass http://dynamic_api;
}
}
}
-
valid=30s是关键:DNS 缓存时间不能设太长(比如 300s),否则后端 IP 变更后 Nginx 仍会持续转发到旧地址,造成 502/504 - 多个 DNS 地址用空格分隔,不支持逗号;失败时会轮询尝试,但不会自动 fallback 到下一个,所以建议至少配两个
-
resolver_timeout要小于valid,否则缓存未过期但查询超时,Nginx 会直接报upstream timed out
upstream 中的 server 必须带 port,且不能省略 resolve 参数
写成 server api.example.com resolve; 会触发 nginx: [emerg] invalid port in upstream 错误。Nginx 动态解析要求明确端口,哪怕只是默认的 80 或 443。
常见错误写法与修正:
- ❌
server api.example.com resolve;→ 缺少端口 - ✅
server api.example.com:80 resolve; - ✅
server api.example.com:443 resolve;(注意:HTTPS 后端需额外配置 SSL 证书验证逻辑) - ⚠️ 不支持
server https://api.example.com:443 resolve;——proxy_pass才处理协议,upstream 只管 host:port
如果后端是 HTTPS,proxy_pass 写 https://dynamic_api 即可,但 upstream 本身不解析协议。
动态解析不等于自动健康检查,必须手动加 proxy_next_upstream
即使用了 resolve,Nginx 默认也不会在某个 IP 失联时自动切到其他解析结果(它只维护一个 IP 列表,不是轮询所有 A 记录)。若 DNS 返回多个 IP,Nginx 默认只用第一个,其余被忽略。
要实现故障转移,必须配合:
-
proxy_next_upstream error timeout http_502 http_503 http_504;(写在 location 内) -
proxy_next_upstream_tries 3;(可选,限制重试次数) -
proxy_next_upstream_timeout 10s;(可选,限制总重试耗时)
否则,哪怕 DNS 已更新、新 IP 已生效,只要旧 IP 还在缓存里且没被主动探测失效,请求仍可能打到宕机节点上。
CentOS 7.9 等老系统要注意 glibc 版本对 DNS 解析的影响
CentOS Linux 7.9(EOL 已超一年)默认 glibc 2.17,其 getaddrinfo() 实现有缺陷:当 DNS 返回 IPv6 地址但网络不通时,可能阻塞整个解析过程,导致 resolver_timeout 生效前就卡住。
规避方式:
- 在
resolver行末尾加ipv6=off(Nginx 1.19+ 支持),例如:resolver 8.8.8.8 ipv6=off; - 或改用纯 IPv4 DNS,如
223.5.5.5(阿里 DNS) - 避免依赖
localhost或127.0.0.1作为 resolver —— 容器或 minimal 系统里 dnsmasq 可能没跑,直接失败
这个点容易被忽略:配置看起来全对,但一上线就偶发超时,查日志全是 connect() failed (111: Connection refused) while connecting to upstream,根源常在这里。


















