DNS 故障切换为什么不是实时的?TTL、缓存和健康检查分别影响什么?
简化版
DNS 故障切换通常不是实时的,因为客户端、递归解析器、操作系统、浏览器和应用连接池都会缓存旧解析结果。
权威 DNS 健康检查发现某个 IP 故障后,可以停止返回它;但已经拿到旧 IP 的用户,在 TTL 过期或连接断开前仍可能继续访问故障节点。
TTL 越低,理论收敛越快,但会增加 DNS 查询量,也不能完全控制不遵守 TTL 的缓存和长连接。
详细版
故障切换链路:
健康检查发现 A 故障 -> 权威 DNS 不再返回 A -> 递归缓存过期 -> 客户端重新解析 -> 新连接打到 B
任何一步都有延迟。
即使 TTL 设置 30 秒,也可能因为:
- 递归 DNS 最小 TTL 策略。
- 浏览器或 JVM DNS 缓存。
- 移动网络 DNS 缓存。
- 应用保持长连接。
- 客户端没有重新解析。
导致故障 IP 继续被访问。
所以 DNS 适合做全局和粗粒度容灾,不适合单独承担秒级实例级故障摘除。
完整版教学
1. 先说明 DNS 切换的基本流程
假设一个域名有两个入口:
api.example.com -> 1.1.1.1
api.example.com -> 2.2.2.2
当 1.1.1.1 故障时,智能 DNS 可以停止返回它。
但已经缓存了 1.1.1.1 的客户端不会立刻忘记。
DNS 故障切换改变的是“新解析答案”,不是立刻改掉全网已经缓存的旧答案。
2. TTL 控制什么
TTL 告诉缓存解析结果可以保存多久。
示例:
api.example.com. 30 IN A 2.2.2.2
理论上递归解析器缓存 30 秒后应重新查询权威 DNS。
TTL 越低,变更理论收敛越快。
但 TTL 低会增加权威 DNS 和递归链路压力。
3. 健康检查控制什么
DNS 服务商的健康检查可以探测节点是否可用。
例如:
- TCP 端口检查。
- HTTP URL 检查。
- 多地域探测。
- 连续失败阈值。
发现故障后,权威 DNS 调整后续响应。
但健康检查本身也有周期和判断阈值,例如连续 3 次失败才摘除。
这也会引入延迟。
4. 缓存层级很多
DNS 缓存不是只有一层。
| 缓存位置 | 影响 |
|---|---|
| 权威 DNS | 控制原始答案 |
| 递归 DNS | 大量用户共享缓存 |
| 操作系统 | 本机解析缓存 |
| 浏览器 | 页面访问缓存 |
| JVM/应用 | 进程内 DNS 缓存 |
| 连接池 | 继续复用旧连接 |
某些应用即使重新解析了,也可能继续使用旧连接,直到连接失败或连接池淘汰。
5. 为什么低 TTL 也不能保证秒切
即使 TTL 是 10 秒,也有现实因素。
- 有些递归 DNS 会设置最小 TTL。
- 有些客户端不严格遵守 TTL。
- 移动端网络切换时缓存行为复杂。
- 应用层连接池不触发重新解析。
- 失败检测和告警本身有延迟。
所以低 TTL 只是提高收敛速度,不是硬实时保证。
6. 更可靠的高可用组合
DNS 常用于机房级、地域级切换。
实例级高可用更适合由负载均衡完成。
常见架构:
DNS 全局调度 -> 区域 LB -> 多实例服务
LB 能实时健康检查和摘除实例。
DNS 在更大粒度上把流量导向可用区域。
7. 常见误区与追问
- 误区:TTL 设置成 0 就能实时切换。 客户端和递归 DNS 不一定按预期处理,且连接池仍可能复用旧连接。
- 误区:DNS 健康检查摘除后所有用户立刻生效。 已缓存旧 IP 的用户还要等待缓存和连接收敛。
- 误区:DNS 可以替代负载均衡健康检查。 DNS 适合粗粒度,LB 更适合实时实例级摘除。
- 追问:为什么故障节点摘掉后仍有流量? 旧 DNS 缓存和长连接仍在使用。
- 追问:低 TTL 有什么代价? 增加 DNS 查询量、权威压力和解析链路依赖。
- 追问:如何设计跨机房容灾? DNS 做地域入口切换,机房内用 LB 和服务治理做细粒度故障处理。
8. 加强记忆
DNS 切换记成“只影响下一次问路,不会抢走已经拿到的旧地图”。
TTL 管地图多久过期,健康检查管新地图给不给坏入口。