options rotate 是客户端侧轮询策略,非真正负载均衡:每次新查询按顺序切换 nameserver,不感知健康状态或延迟,需配合 timeout/attempts 及 DNS 代理等机制弥补短板。

在 /etc/resolv.conf 中启用 options rotate,确实能让系统对多个 nameserver 实现轮询式查询分发,但它本身**不是真正的负载均衡机制**,而是一种客户端侧的简单轮询策略——每次新查询按顺序切换 nameserver,不感知后端健康状态、响应延迟或负载情况。要“合理配置”,关键在于理解它的行为边界,并配合其他措施弥补短板。
rotate 的真实作用与限制
rotate 选项让 resolver 库在每次发起新 DNS 查询时,从 nameserver 列表中按轮转顺序选取下一个服务器(而非始终用第一个)。例如配置:
nameserver 10.1.1.10 nameserver 10.1.1.11 nameserver 10.1.1.12 options rotate timeout:2 attempts:2
→ 第一次查询走 10.1.1.10,第二次走 10.1.1.11,第三次走 10.1.1.12,第四次回到 10.1.1.10,以此类推。
免费 DNS 与邮件安全分析(IntoDNS.ai):包括 DNSSEC、SPF、DKIM、DMARC、MTA-STS、BIMI、SMTP STARTTLS、FCrDNS、黑名单、发件人要求及报告。
- 它不保证请求均匀分布:单个应用进程可能反复复用同一 socket 或连接,导致某台 DNS 服务器被高频调用
- 它不规避故障节点:若 10.1.1.11 响应超时或返回 SERVFAIL,resolver 仍会继续轮到它,除非搭配
timeout和attempts快速失败 - 它不共享状态:不同进程、不同用户、不同容器各自独立轮询,无法全局调度
真正实现“分布式轮询负载均衡”的必要配套
仅靠 rotate 不足以支撑生产级私有 DNS 集群的稳定负载分发。需组合以下实践:
-
上游 DNS 服务自身支持健康探测与自动剔除:如部署 dnsmasq 或 CoreDNS 作为本地代理,配置上游为你的私有 DNS 列表,并启用
health-check或fallthrough+retry机制,由代理层做智能选路 -
统一出口网关或 DNS 代理层集中管理:避免每台客户端单独配置 resolv.conf。推荐部署轻量级本地 DNS 代理(如 dnsmasq 监听 127.0.0.1:53),在代理配置中设置多个 upstream 并开启
server=/#/10.1.1.10,10.1.1.11,10.1.1.12和all-servers或random模式,比 rotate 更灵活 - 配合 systemd-resolved 的 DNS RR 支持(若启用):现代 systemd 版本支持从上游 DNS 返回的多 A 记录做客户端侧轮询(RFC 8305)。此时应确保你的私有 DNS 服务器对同一域名返回多个 IP,并关闭 resolv.conf 中的 rotate,交由 resolver 自动处理
-
禁用冲突机制:确认未同时启用
options single-request-reopen或no-check-names等干扰行为的选项;尤其避免与systemd-resolved共存时手动写死 resolv.conf —— 它会被覆盖,应改用resolvectl dns或 Netplan 设置
推荐的 resolv.conf 配置模板(仅当必须直连多台私有 DNS 时)
若受限于架构必须让客户端直连多台私有 DNS(如无代理层),可采用如下最小化稳健配置:
# /etc/resolv.conf(静态场景下) nameserver 10.1.1.10 nameserver 10.1.1.11 nameserver 10.1.1.12 options rotate timeout:1 attempts:2 ndots:1
-
timeout:1:1 秒超时,避免卡住 -
attempts:2:最多尝试 2 次(含重试),减少长尾延迟 -
ndots:1:仅当域名含至少 1 个点才直接查询,避免短名误触发 search 域补全,降低无效请求 - 确保三台私有 DNS 服务器时间同步、ACL 一致、响应策略相同(如 TTL、缓存策略)
验证是否生效
不要只看 resolv.conf 内容,要实测轮询行为:
- 执行多次
dig +short example.com @127.0.0.1(若走本地代理)或dig +short example.com(直连),观察 TCP/UDP 连接目标 IP 变化(用ss -tnp | grep :53或抓包) - 临时停掉某台 upstream DNS(如 systemctl stop named),检查后续查询是否自动跳过它 —— 若仍持续失败,说明 rotate 未起作用或 resolver 缓存了失败路径,需重启应用或清空 glibc resolver 缓存(部分版本支持
resolvectl flush-caches) - 对比启用/禁用 rotate 时,
time for i in {1..100}; do dig +short google.com >/dev/null; done的总耗时差异

















