Nginx 自建异步 DNS 客户端,依赖 resolver 指令实现运行时动态解析,支持多 DNS 服务器、缓存控制与故障转移,不依赖系统 libc 或 /etc/resolv.conf。

Nginx 对 DNS 解析的处理不是靠系统默认的 libc 解析器“一劳永逸”,而是自建一套轻量、异步、可配置的 DNS 客户端机制,核心目标是支持运行时动态更新上游地址,避免重启服务。
resolver 指令驱动的主动解析体系
Nginx 不在启动时静态解析 proxy_pass 后的域名(除非用 upstream 块且未配 resolver),而是依赖显式声明的 resolver 指令来启用动态解析能力:
- 必须配合变量使用:如
set $backend "api.example.com"; proxy_pass http://$backend;,否则仍走启动期静态解析 - resolver 可定义在 http / server / location 级别,作用域内生效,不同 location 可指定不同 DNS 服务器
- 支持多个 DNS 地址,自动轮询或故障转移(如
resolver 114.114.114.114 8.8.8.8 valid=5s;) -
valid=参数控制缓存有效期,过期后下次请求触发新解析,非后台定时刷新
内部解析流程:从缓存到回调
Nginx 自实现 DNS 查询逻辑,不阻塞事件循环:
- 首次解析时,构造 DNS 查询包,通过 UDP 发往 resolver 配置的服务器
- 结果存入内存红黑树缓存,带 TTL 计时;若命中缓存且未过期,直接返回 IP 列表
- 若为 IPv4 地址字面量(如
set $backend "192.168.1.100";),跳过 DNS 流程,标记quick直接回调 - 解析成功/失败均通过异步回调通知,proxy 模块据此建立连接或触发重试(如
proxy_next_upstream error)
与系统 DNS 的隔离设计
Nginx 显式绕过了系统的 /etc/resolv.conf 和 getaddrinfo():
- 未配置
resolver时,若 proxy_pass 含域名,Nginx 会尝试用系统默认方式解析 —— 但这是启动期同步行为,不可变 - 一旦启用
resolver,整个解析生命周期由 Nginx 自主管理,包括超时、重传、缓存清理 - 不读取
/etc/hosts,本地 hosts 映射对 resolver 无效;如需类似效果,应改用静态 IP 或内部 DNS 服务
典型限制与应对要点
这套机制强大但有边界,实际部署需注意:
- 仅支持 A 和 AAAA 记录,不解析 SRV 或 CNAME 链(K8s Headless Service 的多 A 记录可直接利用)
- 每次解析返回全部 IP(非轮询单个),负载均衡责任移交至 Nginx 的 upstream 算法或客户端逻辑
- valid 值不宜过小(如
- resolver 必须指向可达的 DNS 服务(如 CoreDNS 的
kube-dns.kube-system.svc.cluster.local),不能仅写 service 名而不带完整 FQDN


















