根本原因是jvm或android客户端本地dns缓存过期不刷新,导致主备切换后仍连接旧ip;需通过配置jvm ttl、自定义okhttp dns、清os缓存及架构上引入服务发现来解决。

主备切换后应用连错旧 IP,根本原因往往不是 DNS 服务器没更新,而是客户端(尤其是 JVM 或 Android 应用)本地缓存了过期的解析结果,且默认不主动刷新。解决关键在于打破“永久缓存”惯性,让客户端在切换后能及时获取新地址。
一、JVM 应用:禁用或限制 DNS 正向缓存
JVM 默认将域名→IP 的正向解析结果永久缓存(networkaddress.cache.ttl = -1),这是金融级故障的常见根源。必须显式配置:
- 启动时添加 JVM 参数:
-Dnetworkaddress.cache.ttl=30(单位秒,建议 30–60,避免太短加重 DNS 压力) - 若需彻底禁用缓存(测试/紧急场景),设为
0;但生产环境不推荐设为 0,易引发 DNS 查询风暴 - 反向解析缓存(失败响应)默认 10 秒,一般无需调整,除非遇到大量无效反查
- 注意:该配置需写入启动脚本或容器环境变量,仅改代码或配置中心无效
二、Android 应用:绕过 Java 层 DNS 缓存
安卓系统存在双层缓存:Java 层(InetAddress)和 Native 层(Bionic DNS)。重启或等半小时不是办法,应从网络库层面干预:
免费 DNS 与邮件安全分析(IntoDNS.ai):包括 DNSSEC、SPF、DKIM、DMARC、MTA-STS、BIMI、SMTP STARTTLS、FCrDNS、黑名单、发件人要求及报告。
- 使用 OkHttp 时,自定义
Dns实现,每次请求前强制调用系统解析(如InetAddress.getAllByName(host)),并设置超时防卡死 - 避免使用
OkHttpClient.Builder.dns()的默认静态缓存实例;改用带 TTL 控制的封装 - 如无法发版,可引导用户切换网络(Wi-Fi ↔ 4G)、开关飞行模式——这会重置底层 DNS 状态,比等缓存过期更可控
三、操作系统与中间件:清缓存 + 防复发
即使应用层修复,OS 和 DNS 客户端缓存仍可能拖后腿,需配套动作:
- Windows:以管理员身份运行
ipconfig /flushdns;检查DNS Client服务是否运行 - macOS:Ventura 及更新版本执行
sudo killall -HUP mDNSResponder;旧版加sudo dscacheutil -flushcache - Linux(systemd-resolved):
sudo systemd-resolve --flush-caches - K8s 环境中,Service Mesh(如 Istio)应启用主动健康探测 + 服务发现兜底,而非依赖 DNS 轮询
四、架构层面:减少对 DNS 的强依赖
真正治本的方式是降低 DNS 在关键链路中的角色:
- 数据库连接改用服务发现(如 Nacos、Consul)+ 客户端负载均衡,由 SDK 感知实例上下线
- 主备 VIP 切换场景,优先走内网 DNS + 极短 TTL(如 5 秒),并配合应用层心跳探活
- 所有核心服务调用增加连接建立超时与重试逻辑,失败时主动触发 DNS 重解析(非仅靠缓存失效)










