记录一下那天晚上的排查过程。后端迁移把域名从 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 缓存默认近似永久,要显式关掉。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。
