ad5/
首页 > 快资讯 > 正文

DNS中有哪些值得学习的优秀设计

2023年03月09日 12:38
来源:IT之家  阅读量:5251  

我曾经也当过学生,现在回想起来,会发现,学生时代的男生记忆力贼好,他们总能记住一串复杂神秘的字母数字串域名,有些大神甚至能直接敲 IP 上网。

在每个翻校墙去网吧的夜晚,你总能发现他们会在某个论坛里寻找开源学习资料,完事还不忘在页面底下祝楼主好人一生平安。

原来那时候,他们就已经在学习互联网最重要的开源和分享精神。

每每想起,感动不已。

感动之余。

我们会发现这里面有几个值得一聊的技术性问题。

比如,为什么用域名和 IP 都能上网。

他们之间是什么关系。

往深了聊,我们可以聊到 DNS 的原理,以及它的设计有哪些是值得我们学习的。

今天的话题,我们从为什么要有 DNS 聊起。

为什么要有 DNS

如果我们想要访问某度,你可以在浏览器上的搜索栏里输入 112.80.248.76 这个 IP 地址,直达页面。

通过 IP 访问网页

这样的行为,合法,但有病。

哦,不好意思,伤害到兄弟们了,你们没对象。

但我假设你们有。

用域名访问

而将域名解析为 IP 的过程,也就是查 "通讯录" 的过程,其实就是 DNS协议需要做的事情。

ping 获得 IP

但问题就来了。

然而网站域名,却不一样,据说 2015 年的时候就已经超过 3 亿了。

如果将这 3 亿条记录都放在一个服务器里,会有两个问题。

  • 超过 3 亿条域名数据,数据量过大,并且数据量持续增加

  • 需要承受大量的读请求。每个网站域名都可能会有成千的访问。这加起来,四舍五入也有千亿 qps 了。

显然,如果将 DNS 做成类似手机通讯录这样的单点服务,那是不可能实现这样的能力的,必须得是分布式系统。

于是,问题就变成了,如何设计一个支持千亿 + qps 请求的大型分布式系统。

我知道肯定有人要说:"这是服务只有 10qps 的人该考虑的事情吗?"

虽然我们做的服务可能只有 10qps,但这并不妨碍我们学习 DNS 里优秀的设计。

我们就从 URL 的层次结构聊起。

URL 的层次结构

可以看到,这个域名中间用了两个句点。通过句点符号,可以将域名分为三部分。

其中 com 被称为一级域或顶级域,其他常见的顶级域还有 cn,co 等,baidu 是二级域,www 则是三级域。

除此之后,在 com 后面,其实还有一个被省略掉的句点号。它叫根域。

域名的层次结构

当域名多起来了之后,将它们相同的部分抽取出来,多个域名就可以变成这样的树状层级结构。

层次结构

这时候我们就可以看到,这些域之间其实是一种层级关系,就像是学校,年级,班级那样。

当你想要去定位一个具体域名的时候,你就可以通过这样的层级找到对应的域名。

举个例子。大家应该还记得那句广告词,"三年级 2 班的李小明同学,你妈妈拿了两罐旺仔牛奶给你",其实李小明的妈妈,就是通过,学校、年级、班级的层级形式,一层层找到人。

DNS 的原理

我们重新回来看下大佬们是怎么设计 DNS。

先直接说最重要的结论。

?利用层级结构去拆分服务

?加入多级缓存

接下来展开。

利用 URL 层级结构去拆分服务

DNS 承载的流量压力非常大,必须要做成分布式服务,于是问题的关键就变成了如何拆分服务。

既然 URL 是树状的层级结构,那保存它们的服务,也可以依据这个,非常自然的拆成树状的形式。

一台服务器维护一个或多个域的信息。于是服务就变成了下面这样的层级形式。

查询过程就跟下图一样。

DNS 查询过程

可以看到,原理比较简单,但这里涉及到两个问题。

  • 本机怎么知道最近的 DNS 服务器 IP 是什么?

  • 最近的 DNS 服务器怎么知道根域的 IP 是多少?

我们一个个来回答。

本机怎么知道最近的 DNS 服务器的 IP 是什么?

这个在之前写过的《刚插上网线,电脑怎么知道自己的 IP 是什么?》提到过,插上网线时,机子会通过 DHCP 协议获得本机的 IP 地址,子网掩码,路由器地址,以及 DNS 服务器的 IP 地址。

DHCP 协议

下面是我的 mac 机子,第二阶段 DHCP Offer 中的抓包截图。可以看到,这里面返回的信息里包含了 DNS 服务器的 IP。

offer 阶段

同时也可以在左上角的点左上角的苹果图标-gt; 系统表偏好设置-gt; 网络-gt; 高级-gt;DNS 中查看到 DNS 服务器的 IP 地址。

这里有个小细节,从上面的抓包图里可以看到路由器地址和 DNS 服务器地址,以及 DHCP 服务器地址,其实都是 192.168.31.1,这个其实是我这边的家用路由器的 IP 地址,也就是说一般家用路由器自带这几个功能。

而在某里云服务器里,DNS 服务器也是一样,是通过 dhcp 协议获得。查看 DNS 服务器的 IP 地址也很方便,执行 cat /etc/ resolv.conf 就好了。

这上面的 nameserver 中,可以看出有两台 DNS 服务器,机子会按照文件中出现的顺序来发起请求,如果第一台服务器没反应,就会去请求第二台。

最近的 DNS 服务器怎么知道根域的 IP 是多少?

我们也知道根域,就是域名树的顶层,既然是顶层,那信息一般也就相对少一些。对应的 IPV4 地址只有 13 个,IPV6 地址只有 25 个。

我们可以通过 dig 命令的 + trace 选项来查看一个域名的 dns 解析过程。

而前面提到的传说中的 13 个根域,从字母 a-m,就都在上图中。

但这又引发了一个问题,上面看到的都是域名。

这。。。

"我本来是想通过域名去找 IP 的,你又让我去找其他域名的 IP?"

听起来不科学,这不就死循环了吗。

是的,所以这些根域名对应的 IP 会以配置文件的形式,放在每个域名服务器中。

也就是说并不需要再去请求根域名对应的 IP,直接在配置里能读出来就好了。

下面这个截图是域名服务器里的配置内容。

可以看到 A 开头的根域,它的 IPV4 地址是 198.41.0.4。

加入多级缓存

对于高并发读多写少的场景,加入缓存几乎就是标配。

DNS 也不例外,它加了缓存,而且不止一层。

从在浏览器的搜索框中输入 URL。它会先后访问浏览器缓存、操作系统的缓存/etc/hosts、最近的 DNS 服务器缓存。如果都找不到,才是到根域,顶级域,二级域等 DNS 服务器进行查询请求。

加入缓存后的 DNS 查询顺序

于是请求过程就成了下图这样。可以看到上面提到的好几有缓存的地方我都加了个绿色的小文件图标,优先在缓存里做查询。

加入缓存后的 DNS 查询过程

正因为多级缓存的存在,每一层实际接收到的请求都大大减少了。并且每个人日常访问的网站也就那么几个,所以大部分时候都能命中缓存直接返回 IP 地址。

简单小结下。

DNS 的设计中,通过层次结构将服务进行拆分,流量分散到多个服务器中。

又通过加入多级缓存,让每个层级实际接收到的请求大大减少,因此大大提高了系统的性能。

这两点,是我们做业务开发的过程中可以参考的优秀设计。

但还有一点,是我们大概率学不来的,叫任播,它也为 DNS 实现高并发处理能力提供了重要支持,我会把它放到放到下一篇文章展开聊聊。

协议格式

DNS 是个域名解析系统,而运行在这套系统上的协议,就叫 DNS 协议。

DNS 是应用层协议

下图是它的报文格式。

DNS 报文

字段太多,很晕?这就对了。

我们就挑几个重点的说说。

Transsaction ID 是事务 ID,对于一次请求和这个请求对应的应答,他们的事务 ID 是一样的,类似于微服务系统中的 log_id。

flag 字段是指标志位,有 2 个 Byte,16 个 bit,需要关注的是 QR,OpCode,RCode。

?QR 用来标志这是个查询还是响应报文,0 是查询,1 是响应。

?OpCode 用来标志操作码,正常查询都是 0,不管是域名查 ip,还是 ip 查域名,都属于正常查询。可以粗暴的认为我们平时只会看到 0。

Queries 字段,是指你实际查询的内容。这里其实包含三部分信息,Name,Type,Class。

查询的内容分成三部分信息

?Class 字段就比较有意思了,你可以简单的认为,我们只会看到它填 IN。其实 DNS 协议本来设计出来是考虑到可能会有更多的应用场景的,比如这里还能填 CH,HS。大家甚至都不需要知道它们是什么含义,因为随着时间的发展,这些都已经成化石了,我们知道这个字段的唯一作用,可能就是可以在面试的时候可以随意装个 x,深藏功与名。

Answers 字段,从名字可以看出,跟 Queries 对应,一问一答。作用是返回查询结果,比如通过域名查对应的 IP 地址,这个字段里就会放入具体的 IP 信息。

抓包

原理看完了,来抓个包吧。

我们打开 wireshark。然后执行

DNS_Query

上面的图里是 DNS 查询的内容,可以看到它是应用层的协议,传输层用的是 UDP 协议进行数据传输。截图里标红的部分,也就是上面提到的需要重点关注的报文字段内容。其中 flag 字段是按 bit 展示的,因此抓包里进行了分行展示。

接下来再看下响应的数据包内容。

DNS_Response

可以看到事务 ID跟 DNS 请求报文是一致的。并且 Answers 字段里带有两个 IP 地址。试了下,两个 IP 地址都是可以正常访问的。

总结

?DNS 是非常优秀的高并发分布式系统,通过层次结构将服务进行拆分,流量分散到多个服务器中。又通过加入多级缓存,让每个层级实际接收到的缓存大大减小,因此大大提高了系统的性能。这两点在做业务开发的过程中是可以借鉴的。

?插上网线通网时,本机通过 DHCP 协议获得 DNS 服务器的地址。

?根域服务器的 IP 会以配置的形式加载到每一台 DNS 服务器当中。因此访问任意一台 DNS 服务器都能轻松找到根域对应的 IP 地址。

最后

最后给大家留下两个问题。

DNS 基于 UDP 协议
  • 从抓包可以看出,DNS 在传输层上使用了 UDP 协议,那它只用 UDP 吗?

  • 上面提到,DNS 的 IPV4 根域名只有 13 个,这里面其实有不少都部署在漂亮国,那是不是意味着,只要他们不高兴了,切断我们的访问,我们的网络就得瘫痪了呢?

[责任编辑:许一诺]

郑重声明:此文内容为本网站转载企业宣传资讯,目的在于传播更多信息,与本站立场无关。仅供读者参考,并请自行核实相关内容。