记录一下那天晚上的排查过程。后端迁移把域名从 10.0.1.10 改到 10.0.1.20,TTL 是六百秒,两小时后仍有三分之一的请求打到旧机器,旧机器还没下线。

刚开始盯着「客户端 SDK 自己缓存了解析结果」,折腾了半个多小时,排掉了。

真正麻烦的地方在于,几个原因的现象几乎一样。本地 DNS 缓存没到期就返回旧值。还有一种是应用侧 JVM 或 glibc 有近乎永久的缓存。

不容易想到的是,部分递归 DNS 不严格遵守 TTL。

上来先用不同递归服务器对比解析结果

dig +short api.example.com @8.8.8.8 && dig +short api.example.com @223.5.5.5

然后确认 TTL 是否已被调小

dig api.example.com | grep -A1 'ANSWER SECTION'

随后在应用侧显式设置缓存过期

java -Dsun.net.inetaddr.ttl=60 -jar app.jar

末了统计旧机器上还剩多少连接

ss -tan | grep 10.0.1.10 | wc -l

怎么算真的好了,看的是同一批现象。三个递归服务器返回一致,旧机器上的连接数在一小时内降到零,客户端日志里不再出现旧 IP。

切流量前把 TTL 提前调到六十秒并等一个旧 TTL 周期,比切完再等要快;JVM 的 DNS 缓存默认近似永久,要显式关掉。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189