learn-tech/专栏/周志明的架构课/16_域名解析系统,优化HTTP性能的第一步.md
2024-10-16 06:37:41 +08:00

131 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

因收到Google相关通知网站将会择期关闭。相关通知内容
16 _ 域名解析系统优化HTTP性能的第一步
你好,我是周志明。从今天这节课开始,我们一起来学习下,如何引导流量分配到最合适的系统部件中进行响应。
那么在正式开始学习之前,我们先来了解下所谓的透明多级分流系统的定义。
理解透明多级分流系统的设计原则
我们都知道用户在使用信息系统的过程中请求首先是从浏览器出发在DNS的指引下找到系统的入口然后经过了网关、负载均衡器、缓存、服务集群等一系列设施最后接触到了系统末端存储于数据库服务器中的信息然后再逐级返回到用户的浏览器之中。
这个过程需要经过许许多多的技术部件。那么作为系统的设计者,我们应该意识到不同的设施、部件在系统中,都具有各自不同的价值:
有一些部件位于客户端或网络的边缘能够迅速响应用户的请求避免给后方的I/O与CPU带来压力典型的如本地缓存、内容分发网络、反向代理等。
有一些部件的处理能力能够线性拓展,易于伸缩,可以通过使用较小的代价堆叠机器,来获得与用户数量相匹配的并发性能,并且应尽量作为业务逻辑的主要载体,典型的如集群中能够自动扩缩的服务节点。
有一些部件的稳定服务,对系统运行具有全局性的影响,要时刻保持着容错备份,维护着高可用性,典型的如服务注册中心、配置中心。
有一些设施是天生的单点部件,只能依靠升级机器本身的网络、存储和运算性能来提升处理能力,比如位于系统入口的路由、网关或者负载均衡器(它们都可以做集群,但一次网络请求中无可避免至少有一个是单点的部件)、位于请求调用链末端的传统关系数据库等,都是典型的容易形成单点部件。
所以,在对系统进行流量规划时,我们需要充分理解这些部件的价值差异。这里,我认为有两个简单、普适的原则,能指导我们进行设计。
第一个原则是尽可能减少单点部件,如果某些单点是无可避免的,则应尽最大限度减少到达单点部件的流量。
用户的请求在系统中往往会有多个部件都能够处理响应比如要获取一张存储在数据库的用户头像图片浏览器缓存、内容分发网络、反向代理、Web服务器、文件服务器、数据库等都可能会提供这张图片。
所以,恰如其分地引导请求分流至最合适的组件中,避免绝大多数流量汇集到单点部件(如数据库),同时依然能够、或者在绝大多数时候能够保证处理结果的准确性,在单点系统出现故障时,仍能自动而迅速地实施补救措施,这便是系统架构中多级分流的意义。
那么,缓存、节流、主备、负载均衡等措施,就都是为了达成该目标所采用的工具与手段,而高可用架构、高并发架构,则是通过该原则所获得的价值。
许多介绍架构设计的资料呢,都会以“高可用、高并发架构”为主题,主要聚焦于流量到达服务端后,如何构建强大的服务端集群来应对。
而在这个小章节中,我们是以“透明多级分流系统”为主题,聚焦于流量从客户端发出,到达服务端处理节点前的过程,并会去了解在这个过程中对流量削峰填谷的基础设施与通用组件。
第二个原则是奥卡姆剃刀原则,它更为关键。
奥卡姆剃刀原则-
Entities should not be multiplied without necessity.-
如无必要,勿增实体。-
—— Occams RazorWilliam of Ockham
作为一个架构设计者,你应该对前面提到的多级分流的手段,有一个全面的理解与充分的准备。同时你也要清晰地意识到,这些设施并不是越多越好,在实际构建系统的时候,你要在有明确需求、真正有必要的时候,再去考虑部署它们。
因为并不是每一个系统都要追求高并发、高可用的,从系统的用户量、峰值流量和团队本身的技术与运维能力出发,来考虑如何布置这些设施,才是最合理的做法。
在能满足需求的前提下,最简单的系统就是最好的系统。
所以在这个章节的第一节课当中我们就先来学习一个相对简单但又是全世界最大规模的查询系统即DNS域名解析查询系统我们一起来看看它是如何实现多级分流的。
DNS的工作原理
我们都知道DNS的作用是把便于人类理解的域名地址转换为便于计算机处理的IP地址。
说到DNS我想到了一件事你可能会觉得有点儿好笑我在刚接触计算机网络有一小段时间以后一直都把DNS想像成是一个部署在世界上某个神秘机房里的大型电话本式的翻译服务。直到后来当我第一次了解到DNS的工作原理也知道了世界根域名服务器的ZONE文件只有2MB大小甚至可以打印出来物理备份的时候我就对DNS系统的设计惊叹得不得了。
域名解析对于大多数信息系统尤其是基于互联网的系统来说是必不可少的组件可是现在想想它在我们的开发工作里其实根本没有特别高的存在感通常它都是不会受到重点关注的设施。这就导致了很多程序员还不太了解DNS本身的工作过程以及它对系统流量能够施加的影响而且DNS本身就堪称是示范性的透明多级分流系统非常符合我们这个章节的主题也很值得我们去借鉴。
无论是使用浏览器还是在程序代码中访问某个网址域名如果没有缓存的话都会先经过DNS服务器的解析翻译找到域名对应的IP地址才能开始通讯。
后面我就以www.icyfenix.com.cn为例吧。这项操作是操作系统自动完成的一般不需要用户程序的介入。
不过DNS服务器并不是一次性地把www.icyfenix.com.cn直接解析成IP地址的这个解析需要经历一个递归的过程。
首先DNS会把域名还原为“www.icyfenix.com.cn.”。注意这里最后多了一个点“.”,它是“.root”的意思。早期的域名都必须得带这个点DNS才能正确解析不过现在几乎所有的操作系统、DNS服务器都可以自动补上结尾的点号了。
然后DNS就开始进行解析了。它的解析步骤是这样的
第一步客户端先检查本地的DNS缓存查看是否存在并且是存活着的该域名的地址记录。
DNS是以存活时间Time to LiveTTL来衡量缓存的有效情况的因此如果某个域名改变了IP地址它也无法去通知缓存了该地址的机器来更新或失效掉缓存只能依靠TTL超期后重新获取来保证一致性。后续每一级DNS查询的过程都会有类似的缓存查询操作所以我就不重复说了。
第二步客户端将地址发送给本机操作系统中配置的本地DNSLocal DNS。这个本地DNS服务器可以由用户手工设置也可以在DHCP分配时或者在拨号时从PPP服务器中自动获取。
第三步本地DNS收到查询请求后会按照“是否有www.icyfenix.com.cn的权威服务器”→“是否有icyfenix.com.cn的权威服务器”→“是否有com.cn的权威服务器”→“是否有cn的权威服务器”的顺序依次查询自己的地址记录。如果都没有查询到本地DNS就会一直找到最后点号代表的根域名服务器为止。
这个步骤里涉及了两个重要名词,你需要好好掌握:
权威域名服务器Authoritative DNS是指负责翻译特定域名的DNS服务器“权威”的意思就是说服务器决定了这个域名应该翻译出怎样的结果。DNS翻译域名的时候不需要像查电话本一样刻板地一对一翻译它可以根据来访机器、网络链路、服务内容等各种信息玩出很多花样。权威DNS的灵活应用在后面的内容分发网络、服务发现等课程内容中都还会涉及到。
根域名服务器Root DNS是指固定的、无需查询的顶级域名Top-Level Domain服务器可以默认为它们已内置在操作系统代码之中。全世界一共有13组根域名服务器注意并不是13台每一组根域名都通过任播的方式建立了一大群镜像根据维基百科的数据迄今已经超过1000台根域名服务器的镜像了之所以有13这个数字的限制是因为DNS主要是采用UDP传输协议在需要稳定性保证的时候也可以采用TCP来进行数据交换的未分片的UDP数据包在IPv4下最大有效值为512字节最多可以存放13组地址记录。
第四步现在假设本地DNS是全新的上面不存在任何域名的权威服务器记录所以当DNS查询请求按步骤3的顺序一直查到根域名服务器之后它将会得到“cn的权威服务器”的地址记录然后通过“cn的权威服务器”得到“com.cn的权威服务器”的地址记录以此类推最后找到能够解释www.icyfenix.com.cn的权威服务器地址。
第五步通过“www.icyfenix.com.cn的权威服务器”查询www.icyfenix.com.cn的地址记录。这里的地址记录并不一定就是指IP地址在RFC规范中有定义的地址记录类型已经多达几十种比如IPv4下的IP地址为A记录IPv6下的AAAA记录、主机别名CNAME记录等等。
我给你举一个例子。假设一个域名下配置了多条不同的A记录此时权威服务器就可以根据自己的策略来进行选择典型的应用是智能线路根据访问者所处的不同地区如华北、华南、东北、不同服务商如电信、联通、移动等因素来确定返回最合适的A记录将访问者路由到最合适的数据中心达到智能加速的目的。
可见DNS系统多级分流的设计就让DNS系统能够经受住全球网络流量不间断的冲击但它也并不是没有缺点。
典型的问题就是响应速度会受影响。在极端情况(如各级服务器均无缓存)下,域名解析可能会导致每个域名都必须递归多次才能查询到结果,显著影响传输的响应速度。
如下图所示你可以看到其高达310毫秒的DNS查询速度
首次DNS请求耗时
所以为了避免产生这种问题专门就有一种前端优化手段叫做DNS预取DNS Prefetching如果网站后续要使用来自于其他域的资源那就在网页加载时便生成一个link请求促使浏览器提前对该域名进行预解释如下所示
<link rel="dns-prefetch" href="//domain.not-icyfenx.cn">
而另一种可能更严重的缺陷就是DNS的分级查询意味着每一级都有可能受到中间人攻击的威胁产生被劫持的风险。
我们应该都知道要攻陷位于递归链条顶层的如根域名服务器cn权威服务器服务器和链路是非常困难的它们都有很专业的安全防护措施。但很多位于递归链底层的、或者来自本地运营商的Local DNS服务器安全防护就相对松懈甚至不少地区的运行商自己就会主动进行劫持专门返回一个错的IP通过在这个IP上代理用户请求以便给特定类型的资源主要是HTML注入广告进行牟利。
所以针对这种情况最近几年出现了一种新的DNS工作模式HTTPDNS也称为DNS over HTTPSDoH。它把原本的DNS解析服务开放为一个基于HTTPS协议的查询服务替代基于UDP传输协议的DNS域名解析通过程序代替操作系统直接从权威DNS或者可靠Local DNS获取解析数据从而绕过传统Local DNS。
这种做法的好处是完全免去了“中间商赚差价”的环节不再惧怕底层的域名劫持能有效避免Local DNS不可靠导致的域名生效缓慢、来源IP不准确、产生的智能线路切换错误等问题。
小结
这节课作为“透明多级分流系统”的第一讲我给你介绍了这个名字的意义与来由。在开发过程中没有太多存在感的DNS系统其实就很符合透明和多级分流的特点。所以我也以此为例给你简要介绍了它的工作原理。
根据请求从浏览器发出到最终查询或修改数据库的信息除了DNS以外还会有客户端浏览器、网络传输链路、内容分发网络、负载均衡器和缓存中间件这些位于服务器、数据库之外的组件可以帮助分担流量便于我们构建出更加高并发、高可用的系统。在后面的几节课中我们就会逐一来探讨它们的工作原理。
一课一思
思考一下,你开发的系统中,有使用过哪些分流手段?欢迎给我留言,分享你的做法。
如果你觉得有收获,也欢迎把今天的内容分享给更多的朋友。感谢你的阅读,我们下一讲再见。