假设域名的服务器地址已经更改,但在家打开的是新网站,手机却仍连接到旧服务器。两台设备即使输入相同名称,经过的 DNS 缓存不同,结果也可能暂时不同。重新获取网页的 HTTP 缓存,与查找连接地址的 DNS 缓存,首先就有不同的检查对象。
本文以虚构的图书馆主机 www.library.example 为线索,说明名称解析与缓存的关系。示例名称和时间表都是为了讲解而编写的,并未测量真实服务的响应。目的是区分 DNS 提供地址的过程、变更看起来延迟的原因,以及名称解析之后发生的失败。
1. DNS 为同一个名称提供不同类型的答案
DNS 通过不同类型的记录提供与域名关联的信息。A 表示 IPv4 地址,AAAA 表示 IPv6 地址,一个名称也可能对应多个地址。CNAME 是指向另一个名称的别名,MX 指示接收邮件的服务器,NS 表示相应区域的权威名称服务器。因此,即便查询同一个名称,请求的记录类型不同,答案也可能不同。
正如 Cloudflare 对 DNS 记录的说明,CNAME 的值是另一个名称,而不是 IP 地址。如果需要地址,可能还要继续解析那个名称。另外,在 https://www.library.example/books 中,DNS 处理的主机名是 www.library.example。/books 这样的路径或网页正文并不注册在 DNS 中。设置 CNAME 也不会自动产生改变浏览器地址栏的 HTTP 重定向。
2. 递归解析器怎样找到权威服务器
设备的名称解析功能通常会向已配置的递归解析器询问答案。所需信息如果在缓存中,递归解析器就使用缓存;如果不足,则向其他 DNS 服务器查询,返回最终答案或错误。DNS 术语标准 RFC 9499区分这种代为解析的角色,以及持有自身负责区域信息的权威服务器。理解答案来源时,应先看服务器以哪种角色作出响应。
在没有缓存和中间转发者的简化流程中,解析器先从根服务器获得顶级域名服务器的指引,再从后者获得目标区域权威服务器的指引,最后向权威服务器取得需要的记录或别名。并不是一台根服务器保存着全部网站的 IP 地址。实际流程可能从已有的委派缓存开始,也可能转发给其他解析器,因此不会每次访问都必然完整地重复这一顺序。
3. TTL 是缓存剩余时间,不是全世界的统一时钟
记录的 TTL 是以秒传递的缓存寿命信息。在普通缓存响应中,剩余时间会随保存时间的增加而减少。例如,解析器在 10:00 保存了 TTL 为 300 秒的地址,用同一份缓存于 10:02 回答时,剩余 TTL 约为 180 秒。下表只假设一个解析器,并且它不重新查询、不提前刷新,也不提供过期响应。
| 虚构时间 | 权威服务器中的地址 | 此解析器的处理 |
|---|---|---|
| 10:00 | 旧地址 | 以 TTL 300 秒保存旧地址 |
| 10:01 | 更改为新地址 | 已保存的数据还剩 240 秒 |
| 10:03 | 新地址 | 在剩余的 120 秒内仍可复用旧地址 |
| 从 10:05 开始的第一次查询 | 新地址 | 假设重新查询以替代过期缓存,并获得新地址 |
其他解析器可能更晚才保存这条记录,也可能从未查询过。更新时间不同,无法仅凭一个 TTL 确定全世界用户同时切换的时刻。缓存也可能在到期前丢弃数据,而刷新网页并不会连共享解析器中的缓存一起清除。TTL 是理解 DNS 响应复用的线索,不是整个网页连接或画面更新的时间限制。
4. 何时降低 TTL,以及“不存在”答案的缓存
以前以 TTL 3,600 秒取得旧地址的缓存,不会因为管理员现在把 TTL 降为 60 秒,就立即收到这个变更。计划更换地址时,应事先调整 TTL,并考虑按以前较长期限缓存的响应还能保留多久。较低的 TTL 可能使变更更频繁地得到确认,但也会增加查询负担和对权威服务器的依赖。与其让所有服务使用同一个很小的数字,不如结合变更计划和故障应对进行考虑。
表示名称不存在的 NXDOMAIN,或名称存在但没有所请求类型记录的 NODATA,也可能被缓存。负缓存标准 RFC 2308规定,采用权威服务器 SOA 记录的 TTL 与 SOA 的 MINIMUM 值中较小的一个,作为否定响应的缓存寿命。因此,即便刚刚加入原本不存在的主机,之前的“不存在”答案仍可能保留。只看新 A 记录的 TTL,就以为那个答案的寿命相同,可能会漏掉原因。
5. 固定相同名称、类型和服务器进行检查
检查记录应同时写明查询的准确名称、A 或 AAAA 等类型、所查询的 DNS 服务器以及时间。在安装了 dig 的环境中,可以用 dig example.com A 指定名称和类型。调查实际问题时,要把 example.com 替换成自己需要检查的主机。这个命令只是操作步骤的例子,并不是本文实际执行命令或测量响应时间的记录。
同时查看响应状态,以及 ANSWER 中的名称、类型、值和 TTL。向同一解析器重复发送同样查询,观察 TTL 是否减少,但不能因数值增加就立刻断定发生错误。数据可能已提前刷新,也可能是多个缓存节点中的另一个节点作答。分别记录 A 与 AAAA 的结果,不把两者混在一起,更容易辨认哪类地址存在差异。
管理员可以用同一名称和类型,对比正在使用的递归解析器与管理区域权威服务器的答案。如果有差异,再依次检查缓存剩余时间、权威服务器之间的数据是否一致,以及委派配置。不要把一台公共解析器的答案概括成所有用户的状态。公司网络的内部 DNS,或浏览器独立的 DNS 设置,都可能改变查询路径,所以比较时也应记录连接环境。
6. 分清 DNS 错误、连接错误和例外情况
NXDOMAIN 是名称不存在的响应,NODATA 是没有所请求记录类型的情况。SERVFAIL 则表示服务器无法处理查询这一失败;超时是在规定等待时间内没有收到答案的观察。不能把这些都解释成“域名被删除了”。应先保留是否出现响应码、向哪个服务器查询的信息,才能决定接下来检查什么。
超过 TTL 仍看到旧答案,不一定违反规则。RFC 8767 的 serve-stale 方法规定,在无法从权威服务器刷新信息的例外情况下,可以使用过期信息提高可用性。这不意味着所有解析器都采用相同配置。因此,与其只凭一个 TTL 值断言变更何时生效,不如检查实际所用解析器的行为。
最后,正常查询到地址,也不保证能够成功连接网站。通向该地址的网络、TLS 证书、Web 服务器和应用程序,都是另外的阶段。如果 DNS 已回答预期地址,网页却打不开,应把调查转向接下来的连接阶段。分别记录名称解析答案与网页响应,有助于在清除页面缓存或随意更改 DNS 配置前,更准确地缩小失败所在的范围。