乐趣区

关于java:DNS中有哪些值得学习的优秀设计

为什么要有 DNS

如果咱们想要拜访某度,你能够在浏览器上的搜寻栏里输出 112.80.248.76 这个 IP 地址,中转页面。

这样的行为,非法,但有病

大部分人,连本人对象的电话号码都记不住,又怎么可能记得住这么一串 IP 地址呢。

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

但我假如你们有。

回忆一下,尽管你记不住对象的电话号码,但却不影响你给她打电话。你的操作过程是不是关上 通讯录,输出 ” 富婆 ”,而后就弹出一个电话号码。点击即拨打。

在计算机领域,你大概率也记不住 IP,所以也须要有相似的 通讯录的性能。比方,你只须要输出www.baidu.com,它就能帮你找到对应的 112.80.248.76,而后进行拜访。

其中 www.baidu.com 是 域名,通过这个域名能够取得它背地的 IP 是112.80.248.76

就像一个人能够有多个电话号码一样,一个域名也能够对应有多个 IP 地址。

而将域名解析为 IP 的过程,也就是 查 ” 通讯录 ” 的过程,其实就是DNSDomain Name System,域名零碎)协定须要做的事件。

另外须要留神的是,下面的这个 IP 地址,我写这篇文章的时候能拜访,不代表大家看文章的时候能拜访。因为这背地的 IP 地址是有可能变更的。能够通过应用 ping www.baidu.com取得最新的 IP 地址。

但问题就来了。

普通人的通讯录,个别有一千个电话号码就算是 社交小达人 了,放在通讯录里入不敷出。

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

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

  • • 超过 3 亿条域名数据,数据量过大,并且数据量继续减少
  • • 须要接受 大量的读申请 。每个网站域名都可能会有成千的拜访。这加起来,四舍五入也有 千亿 qps了。

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

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

我晓得必定有人要说:” 这是服务只有 10qps 的人该思考的事件吗?”

尽管咱们做的服务可能只有 10qps,但这并不障碍咱们学习 DNS 里优良的设计。

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

URL 的层次结构

举个例子。一个常见的域名,比方 www.baidu.com

能够看到,这个域名两头用了 两个句点。通过句点符号,能够将域名分为三局部。

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

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

当域名多起来了之后,将它们雷同的局部抽取进去,多个域名就能够变成这样的 树状层级构造

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

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

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

DNS 的原理

咱们从新回来看下大佬们是怎么设计 DNS。

先间接说最重要的论断。

  • • 利用层级构造去拆分服务
  • • 退出多级缓存

接下来开展。

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

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

既然 URL 是树状的层级构造,那保留它们的服务,也能够根据这个,十分天然的拆成树状的模式。

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

当咱们须要拜访www.baidu.com

查问过程就跟下图一样。

申请会先打到最近的 DNS 服务器(比方你家的家用路由器)中,如果在 DNS 服务器中找不到,则 DNS 服务器会间接询问根域服务器,在根域服务器中尽管没有 www.baidu.com 这条记录的,但它能够晓得这个 URL 属于 com 域,于是就找到 com 域服务器的 IP 地址,而后拜访 com 域服务器,反复下面的操作,再找到放了baidu 域 的服务器是哪个,持续往下,直到找到 www.baidu.com 的那条记录,最初返回对应的IP 地址

能够看到,原理比较简单,但这里波及到两个问题。

  • • 本机怎么晓得最近的 DNS 服务器 IP 是什么?
  • • 最近的 DNS 服务器怎么晓得根域的 IP 是多少?

咱们一个个来答复。

本机怎么晓得最近的 DNS 服务器的 IP 是什么?

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

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

同时也能够在左上角的点左上角的苹果图标 -> 零碎表偏好设置 -> 网络 -> 高级 ->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 服务器也不再须要每次都从 根域 开始查起。比方在缓存里能找到 baidu.com 的服务器 IP,就间接跳到二级域服务器上做查找就好了。

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

简略小结下。

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

又通过退出 多级缓存,让每个层级理论接管到的申请大大减少,因而大大提高了零碎的性能。

两点,是咱们做业务开发的过程中能够参考的优良设计。

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

协定格局

DNS 是个域名解析零碎,而运行在这套零碎上的协定,就叫DNS 协定

和 HTTP 相似,DNS 协定也是个 应用层协定

下图是它的报文格式。

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

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

Transsaction ID是事务 ID,对于一次 申请 和这个申请对应的 应答,他们的事务 ID 是一样的,相似于微服务零碎中的log_id

flag 字段 是指标记位,有 2 个 Byte,16 个 bit,须要关注的是QROpCodeRCode

  • • QR用来标记这是个查问还是响应报文,0 是查问,1 是响应。
  • • OpCode用来标记操作码,失常查问都是 0,不论是域名查 ip,还是 ip 查域名,都属于 失常查问。能够粗犷的认为咱们平时只会看到0
  • • RCode是响应码,相似于 HTTP 里的404, 502 这样的status code。用来示意这次申请的后果是否失常。0 是指一切正常。1 是指报文格式谬误,2 服务域名服务器外部谬误。

Queries字段,是指你理论查问的内容。这里其实蕴含三局部信息,NameTypeClass

  • • Name能够放域名或者 IP。比方你要查的是 baidu.com 这个域名对应的 IP,那外面放的就是 域名 ,反过来通过 IP 查对应的域名,那Name 字段里放的就是IP
  • • Type是指你想查哪种信息,比方你想查这个域名对应的 IP 地址是什么,那就是填 A(address),如果你想查这个域名有没有其余别名,就填 CNAME(Canonical Name)。如果你想查 xiaobaidebug@gmail.com 对应的邮箱服务器地址是什么(比方 gmail.com),那就填 MX(Mail Exchanger)。除此之外还有很多类型,上面是常见的 Type 表格。
  • • Class 字段就比拟有意思了,你能够简略的认为,咱们只会看到它填 INInternet)。其实 DNS 协定原本设计进去是思考到可能会有更多的利用场景的,比方这里还能填CHHS。大家甚至都不须要晓得它们是什么含意,因为随着工夫的倒退,这些都曾经成化石了,咱们晓得这个字段的惟一作用, 可能 就是能够在面试的时候能够随便装个 x,深藏功与名。

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

抓包

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

咱们关上wireshark。而后执行

dig www.baidu.com

此时操作系统会收回 DNS 申请,查问 www.baidu.com对应的 IP 地址。

下面的图里是 DNS 查问(request)的内容,能够看到它是应用层的协定,传输层用的是 UDP 协定 进行数据传输。截图里标红的局部,也就是下面提到的须要重点关注的报文字段内容。其中 flag 字段是按 bit 展现的,因而抓包里进行了分行展现。

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

能够看到 事务 ID(Transaction ID)跟 DNS申请 报文是统一的。并且 Answers 字段里带有两个 IP 地址。试了下,两个 IP 地址都是能够失常拜访的。

总结

  • DNS 是十分优良的高并发分布式系统,通过层次结构将服务进行拆分 ,流量扩散到多个服务器中。又通过退出 多级缓存,让每个层级理论接管到的缓存大大减小,因而大大提高了零碎的性能。这两点在做业务开发的过程中是能够借鉴的。
  • 插上网线通网时,本机通过 DHCP 协定取得 DNS 服务器的地址。
  • 根域服务器的 IP 会以配置的模式加载到每一台 DNS 服务器当中。因而拜访任意一台 DNS 服务器都能轻松找到根域对应的 IP 地址。

最初

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

  • 从抓包能够看出,DNS 在传输层上应用了 UDP 协定,那它只用 UDP 吗?
  • 下面提到,DNS 的 IPV4 根域名 只有13 个,这外面其实有不少都部署在丑陋国,那是不是意味着,只有他们不快乐了,切断咱们的拜访,咱们的网络就得瘫痪了呢?
退出移动版