SCAN IP 不能靠 /etc/hosts 轮询解决,因为该文件仅支持单IP映射,glibc 解析器只取首行,无法实现多A记录随机返回;必须依赖合规DNS服务满足三条件:返回全部3个IP、禁用干扰缓存、支持TCP回退。
SCAN IP 为什么不能靠 /etc/hosts 轮询解决
oracle rac 的 scan(single client access name)本质是 dns 负载均衡机制,依赖客户端解析时随机返回多个 a 记录中的一个。而 /etc/hosts 每个主机名只能映射单个 ip,硬写多个条目不会触发轮询——glibc 解析器只取第一个匹配项,后续条目被忽略。
常见错误现象:nslookup scan.example.com 返回三个 IP,但用 ping scan.example.com 总连到同一个 IP;Java 应用连接 SCAN 时始终走固定节点,负载不均。
-
/etc/hosts不支持多值映射,强行写三行192.168.1.10 scan.example.com、192.168.1.11 scan.example.com……只会生效第一行 - 部分旧版 glibc(如 2.17 之前)甚至会因重复主机名报
Unknown host - Oracle 客户端(如 JDBC thin)内部做 DNS 缓存,
/etc/hosts修改后需重启应用才可能刷新
必须用真实 DNS 实现 SCAN 轮询的三个硬性条件
DNS 是 SCAN 正常工作的唯一合规路径,但不是随便配个 A 记录就行。关键在响应行为是否满足 Oracle 要求:
- DNS 服务器必须对同一查询返回全部三个 SCAN IP(顺序可变),不能只返回一个或做内部负载转发
- 禁用 DNS 响应中的
AA(Authoritative Answer)标志位以外的缓存控制干扰(比如某些 BIND 配置加了max-cache-ttl 0导致客户端反复重查,反而加剧抖动) - 客户端所在网络必须能直连 DNS 服务器,且 DNS 查询不经过代理或中间防火墙截断 TCP 回退(SCAN 强制要求 UDP 查询失败后走 TCP,部分安全设备会丢弃 TCP 53 端口的 DNS 包)
典型错误:用 dnsmasq 做本地缓存 DNS,但没配置 no-hosts 和 addn-hosts,导致它把 /etc/hosts 里静态条目优先返回,破坏轮询。
验证 SCAN DNS 行为是否合格的实操命令
别信配置文件,要看实际发包和响应。重点检查返回 IP 数量、顺序随机性、协议回退能力:
- 用
dig scan.example.com A +short连续执行 10 次,输出必须稳定为 3 行 IP,且顺序明显变化(不是每次都一样) - 用
dig scan.example.com A +tcp +short验证 TCP 模式是否返回相同结果(防止 UDP 被限包) - 用
nslookup -debug scan.example.com 192.168.1.1(指定 DNS 服务器)看响应头里ANSWER: 3是否出现,同时确认没有REFUSED或NOERROR但 ANSWER 为 0
如果 dig 返回 IP 少于 3 个,大概率是 DNS 服务端做了视图(view)隔离,或者 ACL 限制了客户端网段,需要查 DNS 日志而非客户端配置。
替代方案:用 VIP 或 GNS 时绕过 SCAN 的代价
真没法配 DNS?可以改用集群每个节点的 VIP 直连,但代价明确:
- JDBC URL 从
jdbc:oracle:thin:@scan.example.com:1521/orcl改成轮询写死三个 VIP,应用层需自己实现故障转移(Oracle UCP 可配,但默认不启用) - RAC 重启节点后 VIP 可能漂移,
/etc/hosts无法自动同步,比 DNS 更容易失效 - GNS(Grid Naming Service)虽能替代外部 DNS,但它依赖 GIPCD 和 OHASD 进程,一旦 CRS 异常,GNS 自身就不可用,运维面更窄
DNS 看似多一层依赖,其实是把解析逻辑下沉到基础设施层;而试图用 /etc/hosts 模拟轮询,等于在错误的抽象层上打补丁,越修越偏。










