理解 DNS 缓存

理解 DNS 缓存

学渣出品,技术/英文学习记录,难免会有理解/翻译瑕疵甚至错误,欢迎指正。
建议阅读原文: Understanding DNS cache

当我第一次学习 DNS 解析 时,我被这个漫长和复杂的过程惊到了。想象一下你每天要访问多少网站,再想一下你每天要访问多少次。现在想象一下你每次访问时,在另一端的 ISP DNS 服务器必须重复整个递归过程,并查询递归链中的所有域名服务器。

以此为背景,想象一下你的手机。当你想跟你一个定期联系的朋友通个电话时,你很容易在最近通话中找到他们的名字并拨打。但是,如果这些信息并没有准备好,你就得打 114 来去获取他们的号码,然后手动拨出。看起来是不是很繁琐?

实际上将域名转化为 IP 地址 需要大量步骤,并且要消耗大量时间。幸运的是,DNS 的设计者考虑到了如何加速 DNS,并实现了缓存。DNS 缓存使得 DNS Server 或者 客户端本地存储 DNS 记录并在以后复用,减少了对新 DNS 请求的查询需求。

域名系统为每一条  DNS 记录实现了存活时间(TTL)。TTL 指定了一条 DNS 记录在 DNS 服务器和客户端可以被缓存的秒数。当缓存中存在该 DNS 记录时,也会保存其存活时长。服务器会持续更新缓存中的 TTL ,以秒为单位倒计时。当它变为 0 时,该记录会从缓存中被删除或者清除。此时,如果缓存过期以后再次收到该记录的请求,DNS 服务器就必须启动解析流程。

要理解缓存,让我们来看下上一篇文章中的例子,解析 www.google.com 。 当你在浏览器里输入 www.google.com 时,浏览器向操作系统询问 IP 地址。操作系统有 stub resolver 或者 DNS client (参考:什么是 DNS Server, resolver 以及 stub resolver),一个操作系统响应所有 DNS 查询的解析器。DNS 解析器会发送 DNS 请求(并开启递归查询标记)给特定的递归解析器(域名服务器)并根据其 TTL 值存储其 DNS 记录到缓存。

Stub Resolver 收到一个应用程序的请求,它会先查看自己的缓存,如果缓存中有该记录,它会将缓存中的信息直接返回给应用程序。如果缓存中没有,则发送 DNS 请求(并开启递归标记)递归解析器(ISPDNS 服务器)。

Recursive Resolver 收到请求,它会先查看缓存中有 www.google.com 的哪些信息。如果缓存中有 A 记录,则把记录发送给 Stub Server。如果没有 A 记录,但是有权威域名服务器的 NS 记录,它将会请求这些权威域名服务器(绕过根服务器和 com gTLD 服务器)。

如果没有权威域名服务器,它会请求 com gTLD 服务器。

graph TD;
google.com-->Browser;
Browser-->OS;
OS-->Stub-Resolver;
Stub-Resolver-->Cached;
Cached-->Browser;
Stub-Resolver-->Not-Cached;
Not-Cached-->ISP-DNS;
ISP-DNS-->Cached-A-Record;
Cached-A-Record-->Stub-Resolver;
ISP-DNS-->Not-Cached-A-Record;
Not-Cached-A-Record-->Cached-Auth-NS-Server;
Cached-Auth-NS-Server-->Query-Auth-NS-Server;
Query-Auth-NS-Server-->ISP-DNS;
Not-Cached-A-Record-->Not-Cached-Auth-NS-Server;
Not-Cached-Auth-NS-Server-->COM-GTLD-Server;
COM-GTLD-Server-->ISP-DNS;
注:图表为译者根据自己理解添加(欢迎指正)

如果没有权威名称服务器,就会请求 .com gTLD 服务器(因为他们 TTL 非常高,他们一般是存在于缓存中,并且他们适用于任意 .com 域名)。只有当他们不存在于缓存时, Recursive Resolver 才会向根服务器请求 gTLDs, 这种情况非常少见(通常是指行了 purge 操作)。

为了避免传播过期 DNS 记录,DNS 服务器将会通过矫正一个请求的 TTL ,而不是这条记录原始 TTL 值。例如,假设 一条 www.google.com 记录的 TTL4 个小时,并且它在上午 8 点被 Recursive Resolver 保存于缓存中。如果有一个新用户,在这个解析器,在上午 9 点请求相同的域名,resolver 将会发送一个 3 个小时的 TTL 记录。

现在我们已经覆盖了 DNSOSDNS 服务器的缓存,然后就剩下最后一层缓存:应用程序。所有应用都可以选择缓存 DNS 数据,即使他们不能遵循 DNS 标准。应用依赖操作系统函数 getaddrinfo() 来解析域名(所有操作系统都是用相同的函数名)。该函数返回域名的 IP 地址列表 - 但是他不返回 DNS 记录,所以应用程序没有 TTL 可用。

所以,不同的应用程序缓存数据时间不同。IE10+ 将在其缓存中存储最多 256 个域名,固定时间为 30 分钟256 个域名看起来好像很多,实际上不是的 - 网络上大量网页都会饮用 50 个域名以上,多亏第三方标记和重定向。另一方面,Chrome 将缓存 DNS 信息一分钟,并且存储 1000 条记录。你可以通过访问 chrome://net-internals#dns 查看和清理 ChromeDNS 缓存。

NS 缓存陷阱

人们会经常掉入一个的 DNS 缓存陷阱是权威名称服务器记录。就像我们之前提到的,权威名称服务器在请求响应中作为 NS 记录被指定。NS 记录有 TTL。但并不提供名称服务器的 IP 地址。IP 信息在额外的 A 或者 AAAA 记录响应里。

因此,一个 Recursive Resolver 同时依赖于 NSA 记录来抵达名称服务器。理想情况下,两种记录类型的 TTL 应该相同,但是偶尔有人错误配置 DNS zones,他们会在 DNS 请求传入新的 A 或者 AAAA 记录。新记录覆盖老记录,导致产生差异。

当所有的记录都在缓存里,Recursive Resolver 将会请求其中一台域名服务器的 IP 地址。如果 Recursive Resolver 缓存中只有 NS 记录,没有 A 或者 AAAA 记录,它就必须解析 名称服务器域名,比如 ns1.google.com, 获取其 IP 地址。这样并不好,因为它增加了解析域的时间。并且,如果它有域名服务器的 A 或者 AAAA 记录但是没有 NS 记录,它会强制发起一个 域名 www.google.comDNS 查询。

设置 TTL: 平衡行为

那么,TTL 时间长一些还是短一些会更好的呢?合适的的情况下,使用一个更长的 TTL,因为它会使 resolvers 缓存更久并且 OSS -- 意味着对终端用户而言意味着更好的性能,以及它会减少到你名称服务器的流量,因为请求会更少。无论如何,它也会减少你的变更 DNS,使你更容易因为遭受 DNS 劫持攻击,并在你的数据中心不可访问时无法设置离线错误页面。

换句话说,TTL 越短人们就越会花时间在下载页面或资源,并增加你名称服务器的压力。并且使你更快的变更 DNS 配置。


DNS 解析是一个多阶段的由互联网大量服务器参与的过程。协议内建的缓存机制通过缓存并复用信息加速了未来 DNS 请求的过程。DNS 服务器 和/或 客户端在 TTL 上遵循该 DNS 规范,但是像浏览器这样的应用程序不遵循该规范 - 因此他们的缓存可以保存任意时间。

你可能感兴趣的