【架构师从入门到进阶】第五章:DNS&CDN&网关优化思路------第一节:DNS优化
在前面的文章中,我们讲过了客户端的优化,从本篇文章开始我们来学习,请求从客户端发出之后到达具体业务逻辑的服务器之前,应该怎么优化,本篇文章我们来学习DNS的优化。
为什么要有DNS
比如说这是我们的客户端client,包括浏览器、APP、安卓、IOS、H5等等;然后后面有一个server端,是我们跑JAVA代码的一个web程序。请求从客户端发出之后,这个请求要到达我们的server端,中间会经历路由器、各种交换机、各种转发、还有光纤等等,最后才能到达我们的这台服务器。

比如说这台服务器的IP地址是"1",这里面会有一个问题,首先是这个"1"它不好记,什么意思呢?
比如说别人问你:"我要查一个东西怎么查?"
你说:"上百度去吧,你直接打开浏览器,输入IP地址,39.44.1.16,你去上这个IP地址,这个地址就是百度。"
他一听,记不住,回去就忘了。
那你说:""你要登www.baidu.com,他就记得住了。
所以一方面是好记,还有一方面更重要的原因是:如果说我在客户端里直接调的这台服务器的IP地址变了,比如说机器坏了我想部署到另外一台机器上,或者通过各种原因机房有迁移。IP地址如果一变,我们APP还得需要发布一个版本,因为APP也需要修改IP地址嘛,这样才能找到新的IP地址。比如新的IP是2,APP也需要改成2,它需要上线发布一个版本,让全国所有的用户都去更新这个APP,就因为你的服务器变了,这样也不合适。

还有一个问题是服务器如果变了,老的服务器根本就访问不了,那么老的那些版本的APP根本就用不了,这是一个很大的风险。

所以说在开发移动互联网项目的时候,用域名是非常有必要的。除非你的用户特别少,就那么几个人,坏就坏了,我赶紧的发个版更新一下,喊一嗓子:"你去更新吧"。
DNS域名解析系统
那么既然用域名是很有必要的,那么中间有一个系统叫DNS(Domain Name System)就是域名解析系统,这个系统目的就是将域名解析成IP地址。

这是我们中间环节里很重要的一个部分,那么这个部分我们怎么去优化它?我们得先了解这个部分由什么组成,以及它的解析过程是什么样子的。
如果让你做一个域名系统,你应该怎么去做?首先,域名系统做的是什么?做的是域名和IP地址的映射,那么我们在一个系统里把域名和IP地址的这种映射关系先给保存下来。是不是我们的数据存储就是这个样子的?当有一个人申请一个新的域名之后,我们要给里面添加一个域名和IP地址的映射,如果IP地址有变更之后,我们要去修改它,有的人要去访问这个域名,我们得来查他,然后这个域名作废了,或者IP作废了,就是这个网站的公司倒闭了,我们得去删除它。所以说有了数据存储之后,再结合上CRUD,一个域名系统就做出来了。

DNS的解析过程
DNS的解析过程学习之前,我们需要了解域名记录的类型有哪些。
域名记录的类型
- A:代表Address。它记录了,域名到IP的映射关系。也就是我存的是A记录,那么我存的就是比如说www.baidu.com到39.14.15.15。
- CNAME:CNAME的记录是域名到域名的映射关系。差不多是别名的意思,比如我要查www.baidu.com,然后你给我指向到另外一个域名,然后另外一个域名再指向一个ip。
- NS:NS记录的是域名到域名解析服务器的映射。比如你来我这查abc.com这个域名,我不知道,然后我告诉你,你去另外一台域名服务器去查吧。就是把域名服务器的地址告诉你,然后你再问另外一台域名服务器abc.com是什么。

域名服务器的类型
好了,在理解DNS解析过程之前,我们还需要学习一点东西,叫做域名服务器的类型。域名服务器的类型有哪些呢?
- 根域名服务器:全世界有13个更域名服务器,全球所有的网站都在来访问它,全球根域名服务器是一个点"."表示的,也就是说你访问www.baidu.com,后面还有一个点".","www.baicu.com.",这个点就是根域名服务器。
- 顶级域名服务器:这个域名当中的".com",就是顶级域名服务器,还有".edu"、".cn"、".gov"、".org"、".net",这个叫顶级域名服务器,也叫做一级域名服务器。
- 二级服务器:baidu.com就是二级域名服务器。
- 权威域名服务器:负责对请求做出权威的回答。就是你问我这个域名对应哪个IP,我告诉你它是哪个IP,或者说我告诉你这个域名对应哪个域名,或者说这个域名你要去哪里去查。权威服务器它做的事情就是他知道IP告诉你IP,知道域名的对应域名告诉你域名,然后知道域名解析服务器告诉你域名解析服务器,就是权威的回答。
- LDNS:本地DNS,也可以叫做递归DNS,但是最终我们把它叫做LDNS。它是直接跟客户端对接的,客户端你来问我,我负责去把下面的好多流程给你走完,我负责问权威服务器或者根服务器等等,最后通过我给问我的人一个最终的答案。

那么这个根域名服务器,全球只有这么13台,现在上网的用户这么多,网站又那么多,一个人打开电脑同时访问多个网站,全球几十亿人,就这13台域名服务器,它是根本扛不住的。他怎么做呢?它这个13个只是一个逻辑上的概念,每个根域名服务器背后有很多,好多好多台,真正的物理服务器在工作。截止二零二零年的八月份,全球一共有将近1100台根服务器,并且每一个根服务器还有好多个镜像服务器,分布在全球不同的地方。根服务器就已经有1000多台,然后每一台还有好多个镜像。在二零二零年八月份之前,我国北京有五个根镜像,上海杭州武汉郑州悉尼贵阳广州香港台北有好多个。
所以说不用担心根域名服务器扛不住,并且域名服务器就那么简单,就是一个增删改查,没有太复杂的业务逻辑,后面还会讲DNS的缓存,缓存在无数个网络节点当中,甚至缓存在你的本机,所以说根域名服务器完全能扛得住全球这么多人上网。
DNS的解析过程
好了,我们到这里开始要学DNS的解析过程。知道它的解析过程了,我们才知道应该从哪里去入手去优化它。
教科书上的答案
先说一个标准的教科书上的答案。

- 这是一个客户端client,它去问LDNS说:"www.baidu.com的IP地址是多少"。
- 然后LDNS会先从根域名服务器问起。
- 然后根域名服务器说:"我没有时间管这么细的问题,你去问点.com域名服务器吧"。
- 然后它就回来,拿到.com域名服务器的地址。
- 又去问.com的域名服务器,.com的域名服务器说:"你问的我这是三级地址啊,你是www.baidu.om呀,我也记不了这么多事情,你问一个叫权威服务器的人吧,ns.baidu.com,你去问他吧"。
- 然后它就获取到ns.baidu.com的地址,继续问那个权威服务器:"www.baidu.com的地址是多少呀"。
- 正好这个权威服务器里面就管着www.baidu.com对应的IP地址,然后它可能给出一个IP地址,,也可能给出的是一个别名,然后也可能说:"你再去另外一个权威去查吧,然后我告诉你baidu.com的地址,你再去查www.baidu.com的地址"。
- 经过这么多经历,走完之后,它拿到了一个IP地址,返回给客户端这个IP地址。
大家看这套流程是不是听着挺耗时的,这是标准答案,从根找起,一级一级往前找,先找到根域名服务器,然后再找到.com服务器,然后再找到baidu.com,然后再找到www.baidu.com,一级一级找。
实际情况
但是,实际情况中,不会这样的,如果这样的话,那根服务器得承受多大的压力。第一是根服务器不太好扛得住这么多压力;第二个是我们自己也忍受不了,每次都从头问一遍,何必呢?
其实呢,实际情况是什么?

我们的client要访问某一个域名的时候,比如说还是www.baidu.com,我先看我的浏览器有没有对它进行缓存,就是我们浏览器有没有把这个域名映射到IP的一个缓存,如果有,那我直接用就好了;
如果没有,我再去问我的操作系统,看操作系统有没有,如果有就返回,我就用;
如果没有,我再去查看hosts文件有没有配置,如果有,那就直接用;
如果没有我再去,问LDNS,LDNS也看看自己有没有,如果有就返回;如果没有,再看有没有baidu.com的域名服务器的解析地址,如果有就返回,那么接着去baidu.com找www.baidu.com的地址;如果这个也没有,那么再去找有没有.com的域名服务器的地址,如果有,再去问.com找baidu.com,找完baidu.com再找www.baidu.com;如果说这些全部都找不到,那没办法,我们再去找根域名服务器,再通过根域名服务器,后再往前找。
大家可以看到,顺序正好是相反的,我们刚才说的教科书式的是从后往前找,而实际工作中是利用缓存从前往后找。能早早的找到,那不是早早的节省时间吗?所以说这是我们的实际工作中的一种做法,这就是DNS的一个解析过程。
DNS优化
那么我们知道了这个解析过程,我们是不是就知道了,应该怎么去优化它呢?根据实际情况应该怎么去优做优化?
- 第一:提前做好DNS缓存。
- 第二:一个域名映射多个IP。
如果平时做过域名映射的话,可以知道一个域名可以映射多个IP。那么,这个有什么好处呢?一个域名映射多个IP,是不是就相当于分流?比如说一个域名映射了两个IP啊,你有1000个请求,而你的服务器只能扛500个请求,那么你通过一个域名映射两个IP,就把这1000个请求分发到两个服务器上了,用DNS做了负载均衡。

我们的方案有这么两种,那么这两种方案有什么优缺点呢?先把这个优缺点给说了,然后再说具体做DNS缓存应该怎么做。
首先用DNS,它的优点配置简单,无成本费用,因为我们这个成本是DNS服务器的成本,我们不需要去买它,当然域名服务需要买,但是我们不需要去搭建,省去了管理DNS服务器的麻烦,用它就这么一个好处。
缺点就是它不受我的控制,我要去添加修改一个域名和一个IP的映射,是需要有生效时间的。如果说我的一台服务器坏了,我对应一个域名是a,那么一时半会域名服务器就算我更新了一台,全球有那么多台域名服务器需要同步,它是需要一定的时间的,那么在这段时间里,DNS服务器还是把我的域名解析到我坏之前的那台服务器上,所以呢,就会导致用户的访问失败。
还有一个缺点,它不能按需分配负载,就是说我给一个域名配置了两个IP域名服务器,它并不知道我这两个IP地址对应的服务器哪个负载更大,如果说负载小的那个就给它发更多的请求,减轻那个负载大的压力,但是DNS服务器它做不到这些,人家也没必要做这些。
所以说,实际部署工作中,我们一般会用DNS域名解析,做第一次的负载均衡。然后为了达到更加合理的负载均衡,就像刚才所说的,哪个服务器的负载压力小,我们把请求导向它,那么这个时候,我们就需要自己用反向代理了。那这样的话就,就能更合理的去利用这些DNS的特性。

好了,我们现在把它的优点和缺点说完之后,我们已经知道要用DNS做缓存和做负载均衡,负载均衡的方法,已经说过了,先做DNS一层负载均衡,然后再接着用我们的反向代理做我们自己的负载均衡。
我们接着说DNS做缓存怎么去做。我们知道DNS在解析的过程中需要很多个环节,我们要减少dns的解析,什么叫减少dns解析?如果说能在一个域名下,那我们就把所有的接口放到一个域名下。这样的话,不需要他去解析额外的域名。
如果说实在不行,必须要两个域名服务器呢?那么,我们可以做DNS的预获取,预获取叫做"dns-prefetch"。一个DNS解析,可能涉及到多级DNS服务,我们要节省这个时间,如果说在某一个页面里,我现在访问的是a页面,通过a页面跳转到b页面,如果说b页面是另外一个域名,或者说另外一个资源在a页面中,我需要点一个音频,点一个视频,那个音频视频是另外一个域名。那么,我们在访问a页面的时候,就提前把后面的那个b域名给它解析掉。这样的话,当访问后面域名的时候,我们就省了解析的时间了,就是说a页面展示的时候,后端有一个悄悄的服务去解析b了。

html
<meta http-equiv="x-dns-prefetch-control" content="on">
html
<link rel="dns-prefetch" href="需要预解析">
但是dns-prefetch需要慎用,为什么呢?因为多页面重复的DNS预解析,会增加DNS的查询次数,会占用公共的资源。当然这是一个对开发者的一个君子协定,道德上的协定。因为有开发者指出,如果说禁用了DNS预读取,每个月能节省100亿次的DNS查询。
然后后面就是DNS的负载均衡,DNS的负载均衡呢,这个就比较简单,我配A记录的时候,把A记录对应两个IP或者多个IP就可以了,它可以配置多个IP,就是我们有多少个后端的服务器就配置多少个。