乐趣区

网络协议 16 – DNS 协议:网络世界的地址簿

    为什么在地址栏输入域名,就能直接访问到对应服务器?全局负载均衡和内部负载均衡又是什么?这些都和 DNS 解析息息相关,让我们一起来解密 DNS 解析。
    其实说起 DNS 解析,应该都知道它很像地址簿。就像我们去一家新开的沃尔玛超市,通过地址簿查出来沃尔玛在哪条路多少号,然后再去找。
    在网络世界中,也是这样的。我们可以记住网站的名称,但是很难记住网站的 IP 地址,因此需要一个“地址簿”,帮我们将网站名称转换成 IP。这个“地址簿”就是 DNS 服务器。
DNS 服务器
    对于 DNS 服务器而言,全球每个人上网,都需要访问它。而全球的网民数,据最新统计,已经有 40 亿,每个人都访问它,可想而知 DNS 服务器会有很大的访问流量压力(高并发)。而且,它还非常重要,一旦出了故障,整个互联网都将瘫痪(高可用)。此外,上网的人分布在全世界各地,如果大家都去同一个地方的某一台服务器,时延将会非常的(分布式)。
    因此,DNS 服务器一定要具备高可用、高并发、分布式的特点。
    基于此,DNS 服务器设计成树状的层次结构。如下图:

根 DNS 服务器:返回顶级域 DNS 服务器的 IP 地址;
顶级域 DNS 服务器:返回权威 DNS 服务器的 IP 地址;
权威 DNS 服务器:返回相应主机的 IP 地址。

DNS 解析流程
    上面说了 DNS 服务器面临大流量访问的压力,因此,为了提高 DNS 的解析性能,很多网站都会就近部署 DNS 缓存服务器。所以,我们常见的 DNS 解析流程就变成了:

客户端发出 DNS 请求给本地域名服务器。我们访问博客园,客户端会问本地域名服务器,www.cnblogs.com 的 IP 是什么?(本地域名服务器,如果网络是通过 DHCP 配置,本地 DNS 是由你的网络服务商,如电信、联通等自动分配,它通常就在网络服务商的机房里);

本地 DNS 收到来自客户端的请求,查找“地址簿”,返回 IP 或请求根域名服务器。我们可以理解为服务器上缓存了一张域名与 IP 对应的大表,如果能找到 www.cnblogs.com,就直接返回对应的 IP 地址。如果没有找到,本地 DNS 会去问它的根域名服务器;

根 DNS 收到来自本地 DNS 的请求,返回 .com 对应的顶级域名服务器的地址。根域名服务器是最高层次的,全球共有 13 套,它不直接用于域名解析,而是指明怎样去查找对应 IP。它发现请求的域名后缀是 .com,就会返回 .com 对应的顶级域名服务器的地址;

本地 DNS 服务器收到顶级 DNS 服务器地址,请求顶级 DNS 服务器查询域名 IP;

顶级 DNS 服务器返回权威 DNS 服务器地址。顶级域名服务器就是大名鼎鼎的,负责 .com、.net、.org 这些二级域名,比如 cnblogs.com,它会返回对应的权威 DNS 服务器地址;

本地 DNS 服务器收到权威 DNS 服务器地址,请求权威 DNS 服务器查询域名 IP。而 cnblogs.com 的权威 DNS 服务器就是域名解析结果的原出处;

权威 DNS 服务器返回对应 IP。权威 DNS 服务器查询“地址簿”,获取到域名对应 IP 地址,返回给本地 DNS 服务器;

本地 DNS 服务器收到 IP,返回给客户端;

客户端与目标建立连接。

    至此,我们完成了 DNS 的解析过程,整个过程如下图:

负载均衡
    站在客户端角度,上述过程是一次 DNS 递归查询过程。因为本地 DNS 全权为它代劳,它只要坐等结果就好了。在这个过程中,DNS 除了可以通过名称映射为 IP 地址外,它还可以做另外一件很重要的事 – 负载均衡。
    还是拿我们逛沃尔玛超市为例。它可能在一个城市里会有多家店,我们要逛沃尔玛,可以就近找一家,而不用都去同一家,这就是负载均衡。
DNS 做负载均衡也有花样可以玩。1)DNS 做内部负载均衡    所谓的内部负载均衡,其实很好理解。就像我们的应用访问数据库,在应用里配置的数据库地址。如果配置成 IP 地址,一旦数据库换到了另外一台机器,我们就要修改配置。如果我们有很多台应用同时连一个数据库,一换 IP,就需要将这些应用的配置全部修改一遍,是不是很麻烦?所以,我们可以将数据地址配置成域名。在更换数据库位置时,只要在 DNS 服务器里,将域名映射为新的 IP 地址就可以了。
    在这个基础上,我们可以更进一步。例如,某个应用要访问另外一个应用,如果配置另外一个应用的 IP 地址,那么这个访问就是一对一的。但是当被访问的应用因流量过大撑不住的时候,我们就需要部署多个应用。这时候,我们就不能直接配置成 IP,而是要配置域名了。只要在域名解析的时候,配置好策略,这次返回一个 IP,下次返回第二个 IP,就实现了负载均衡。
2)DNS 做全局负载均衡    为了保证我们应用的高可用性,往往会将应用部署在多个机房,每个地方都会有自己的 IP 地址。当用户访问某个域名的时候,这个 IP 地址可以轮询访问多个数据中心。如果一个数据中心因为某种原因挂了,只要将这个 IP 地址从 DNS 服务器中删掉就可以了,用户不会访问到宕机的服务器,保证了应用的可用性。
    另外,我们肯定希望用户能访问就近的数据中心。这样客户访问速度就会快很多,体验也会好很多,也就实现了全局负载均衡的概念。
负载均衡示例
    我们通过 NDS 访问数据中心对象存储上的静态资源为例,来看一看整个过程。
    假设全国有多个数据中心,托管在多个运营商,每个数据中心有三个可用区。对象存储可以通过跨可用区部署,实现高可用性。在每个数据中心中,都至少部署两个内部负载均衡器,内部负载均衡器后面对接多个对象存储的前置服务器(Proxy-server)。那么,请求过程如下图:

当一个客户端要访问 object.yourcompany.com 的时候,需要将域名转换为 IP 地址进行访问,所以它要请求本地 DNS 解析器;
本地 DNS 解析器先查看本地的缓存是否有这个记录。如果有,就直接用,省略后续查询步骤,提高相应时间;
如果本地无缓存,就需要请求本地的 DNS 服务器;
本地 DNS 服务器一般部署在数据中心或者你所在的运营商网络中。本地 DNS 服务器也需要看本地是否有缓存,如果有,就直接返回;
本地没有,通过第 5、6、7 步骤获取到 IP 地址,缓存到本地 DNS 解析器中,然后在返回给客户端。

    对于不需要做全局负载均衡的简单应用来讲,yourcompany.com 的权威 DNS 服务器可以直接将 object.yourcompa.com 这个域名解析为一个或者多个 IP 地址,然后客户端可以通过多个 IP 地址,进行简单的轮询,实现简单的负载均衡。
    但是对于复制的应用,尤其是跨地域跨运营商的大型应用,就需要更加复杂的全局负载均衡机制,因而需要专门的设备或者服务器来做这件事情,这就是全局负载均衡器(GSLB,Global Server Load Balance)。
    在 yourcompany.com 的 DNS 服务器中,一般是通过配置 CNAME 的方式,给 object.yourcompany.com 起一个别名。例如 object.vip.yourcompany.com,然后告诉本地 DNS 服务器,让它请求 GSLB 解析这个域名,GSLB 就可以在解析这个域名的过程中,通过自己的策略实现负载均衡。
上图中画了两层的 GSLB,是因为分运营商和地域。我们希望不同运营商的客户,可以访问对应运营商机房中的资源,这样不跨运营商访问,有利于提高吞吐量,减少时延。两层 GSLB 的过程如下:

第一层 GSLB,通过查看请求它的本地 DNS 服务器所在的运营商,就知道用户所在的运营商。假设是移动,通过 CNAME 的方式,通过另一个别名 object.yd.yourcompany.com,告诉本地 DNS 服务器去请求第二层的 GSLB;
第二层 GSLB,通过查看请求它的本地 DNS 服务器的地址,知道用户所在的地理位置,然后将距离用户位置比较近的一个 Region 的六个内部负载均衡的地址,返回给本地 DNS 服务器;
本地 DNS 服务器将结果返回给本地 DNS 解析器;
本地 DNS 解析器将结果缓存后,返回给客户端;
客户端开始访问属于相同运营商的,且距离比较近的 Region1 中的对象存储。当然,客户端得到了六个 IP 地址,它可以通过负载均衡的方式,随机或者轮询选择一个可用区进行访问。对象存储一般会有三个备份,从而实现对存储读写的负载均衡。

小结

DNS 是网络世界的地址簿。可以通过域名查地址,因为域名服务器是按照树状结构组织的,因而域名查找是使用递归查询的方式,并通过缓存的方式加快效率;
在域名和 IP 的映射中,给了应用基于域名做负载均衡的机会,可以是简单的负载均衡,也可以是根据地址和运营商做的全局负载均衡。

参考:

维基百科 - 域名系统 词条;

知乎 - 域名解析;
刘超 – 趣谈网络协议系列课;

退出移动版