代理网关切换时如何排查陈旧 DNS 缓存

明亮的网络运维工作台在新旧代理网关集群之间刷新并切换 DNS 缓存

代理网关域名已经指向新地址,运行中的任务却仍可能使用旧路径。原因通常不是一个缓存,而是多层状态叠加:权威 DNS、递归解析器、操作系统、应用运行时、HTTP 客户端以及已经建立的连接池,都可能按不同周期保留信息。

本指南面向使用住宅代理、轮换代理开展合规数据采集、市场研究与广告验证的运维团队。目标是定位哪一层保留了旧状态,证明新网关可以工作,并保证切换期间不会出现不安全的直连回退。

先区分三类故障

不要把所有解析错误都叫作“DNS 陈旧”:

  1. 正向缓存陈旧:仍返回或复用旧的 A、AAAA 地址。
  2. 负向缓存持续:域名恢复后,先前的 NXDOMAIN 或无数据结果仍被缓存。
  3. 连接复用:DNS 已更新,但客户端继续使用连向旧地址的 TCP、TLS 或 HTTP/2 连接。

三种问题需要不同处理。一次性重启全部工作进程可能掩盖原因,还会制造重试洪峰。

画出全部解析与复用层

针对代理网关域名记录:

  • 权威 A、AAAA、CNAME 与 TTL;
  • 生产任务使用的递归解析器;
  • 容器、虚拟机或主机的解析配置;
  • 运行时使用的解析 API;
  • 客户端库的 DNS 缓存策略;
  • 连接池空闲时间与最大寿命;
  • 代理会话寿命和粘性规则;
  • 负载均衡器或网关健康行为。

Node.js 的 dns.lookup() 通常使用操作系统解析能力,而 dns.resolve*() 会执行网络 DNS 查询,配置路径并不相同。因此,诊断脚本和真实应用如果使用不同 API,结果可能不一致。

libcurl 还维护内存 DNS 缓存。官方文档说明默认缓存时间为 60 秒,且不直接采用 DNS 记录 TTL。当前版本对权威“域名不存在”结果与临时、本地解析故障的缓存方式也不同。解释测试前必须记录客户端版本。

建立切换前基线

在每个生产地区运行小规模授权金丝雀,并只保存脱敏证据:

timestamp
workload_region
resolver_alias
gateway_hostname_alias
answer_family
answer_set_hash
dns_lookup_ms
new_connection_or_reuse
connected_gateway_alias
proxy_auth_result
observed_exit_market
request_result

不得记录代理密码、令牌、Cookie、客户标识或完整敏感目标 URL。

A 与 AAAA 必须分别验证。IPv4 成功不能证明 IPv6 路径正常,地址顺序变化也可能改变运行时优先尝试的地址族。

分阶段执行网关切换

1. 提前降低权威 TTL

应预留足够时间,让旧 TTL 在常见解析器中到期,并从多个生产地区确认新值。修改地址时才降低 TTL,不能缩短已经按旧值缓存的记录。

2. 先加入新地址,再移除旧地址

架构允许时,让新旧健康网关短期重叠。全量迁移前验证新网关的代理认证、TLS 主机名、允许的方法、带宽、出口选择和日志。

3. 不改 DNS,单独固定一次金丝雀连接

使用安全的客户端机制,把网关域名和端口仅在单次金丝雀中绑定到新地址。必须保留域名用于 TLS 和代理认证,不能在生产配置中直接换成裸 IP。固定测试可以把网关可用性与解析器行为分开。

4. 比较冷进程与热进程

用同一请求比较:

  • 没有应用缓存的新进程;
  • 已有 DNS 缓存的热进程;
  • 为金丝雀关闭连接复用的热进程;
  • 正常生产连接池。

如果只有生产连接池仍连接旧地址,应先检查连接寿命,而不是盲目刷新 DNS。

5. 证据收敛后才移除旧地址

要求所有必要地区都获得预期地址集合、新连接成功、代理出口正确、应用结果稳定,并保留明确回滚窗口。

单独诊断负向缓存

NXDOMAIN 必须有自己的时间线。RFC 2308 规定了使用区域 SOA 信息进行负向缓存。权威解析曾返回域名不存在时,即使记录马上恢复,部分客户端也可能要等负向缓存到期后才能看到。

处理负向缓存事件时:

  1. 确认权威结果是 NXDOMAIN、无数据、超时还是本地故障;
  2. 检查决定负向缓存寿命的 SOA 值;
  3. 查询生产递归解析器,而不只使用公共诊断解析器;
  4. 比较全新解析路径和受影响应用;
  5. 负向记录有效期间避免紧密重试;
  6. 在预期到期时间后验证恢复。

不能把每次查询失败都转成地址轮换。临时解析器故障与权威域名不存在是两种不同信号。

让代理保持失败关闭

DNS 故障时,强制代理任务不得删除代理设置或直接访问目标。验证:

  • 代理域名无法解析时,任务停止或进入有上限的队列;
  • 旧地址不能绕过代理认证;
  • 备用网关经过明确批准和独立测试;
  • 恢复期间 NO_PROXY 范围不会扩大;
  • 重试包含指数退避、抖动和总预算;
  • 排队任务有过期时间和花费上限。

首试成功率与最终成功率要分开记录。最终 100% 成功仍可能掩盖数分钟错误路由和大量重试。

决策表

观察可能层级下一步
递归查询仍返回旧地址上游缓存等待有效 TTL 或修正权威数据
递归结果已新,应用结果仍旧系统或运行时缓存检查解析 API 与进程缓存
查询已新,连接仍到旧地址连接池受控排空或缩短连接寿命
A 已更新但 AAAA 仍旧地址族路径分别测试 IPv4 与 IPv6
域名恢复后仍失败负向缓存核对 NXDOMAIN 寿命和到期时间
代理域名失败后流量直连策略缺陷停止任务并修复失败关闭路由

验收清单

  • [ ] TLS 与认证继续使用同一正确网关域名。
  • [ ] 新旧 A 与 AAAA 集合已记录。
  • [ ] 计划窗口后权威与递归结果一致。
  • [ ] 冷进程和热进程都已测试。
  • [ ] 新建连接与复用连接可区分。
  • [ ] 新网关通过认证和出口地区验证。
  • [ ] 直连回退已阻断。
  • [ ] 重试和队列预算可防止恢复风暴。
  • [ ] 日志不包含凭据或敏感 URL。
  • [ ] 所有地区证据收敛后才移除旧网关。
  • [ ] 回滚标准和负责人已记录。

相关控制可参考 98IP 的代理故障切换恢复演练SOCKS5 远程 DNS 测试代理服务 SLA 验证手册

常见问题

应用 DNS 缓存必须完全遵循记录 TTL 吗?

不一定。客户端库和操作系统可能有独立缓存策略。应记录生产技术栈的真实行为,不能假设权威 TTL 控制所有层。

刷新 DNS 就够了吗?

不够。DNS 已更新后,现有连接仍可继续使用旧网关。先在金丝雀中关闭连接复用;如果原因确为复用,再渐进排空连接池。

是否应该把 DNS 缓存设为零?

通常不应作为通用修复。禁用缓存会增加解析器负载和延迟。应选择符合切换目标的有限缓存与连接寿命,并在负载下验证。

可以把代理域名换成裸 IP 吗?

这可能破坏 TLS 主机名验证、网关路由与运维灵活性。诊断时使用受控固定机制,同时保留预期域名。

合规说明

仅将代理用于合法、已授权的任务。遵守目标条款、robots 指示、访问控制、隐私义务和限流。不得利用 DNS 变更、备用网关或重试规避访问决定。只保留可靠性和合规所需的诊断数据。

内部研究依据:curl 项目的 DNS 缓存时间文档、Node.js DNS 文档、IETF RFC 2308 负向 DNS 缓存规范。来源 URL 仅保存在内部运营记录中。