什么是CDN?它的工作原理是怎样的?

分类: 架构设计

保留所有版权,请引用而不是转载本文(原文地址 https://yeecode.top/blog/136/ )。

我们部署的软件系统处在互联网的某个节点上,图 1展示了这种情况,通常这个节点由一个 IP 地址标定。所有指向该系统的请求,都会在网络上经过多次路由后到达该节点。

网络上的系统
图 1:网络上的系统

如果我们在网络的多个位置都部署这套系统,就可以把请求分散到多个系统上,减少每个系统承担的并发请求数。不仅如此,还可以让每个用户的请求落到离他最近的一个系统上,这样便降低了网络延时,从而减小平均响应时间,可谓一举两得。

这里所说的"最近",不是地理位置上的最近,而是网络拓扑结构上的"最近"。在网络拓扑中,一个节点到另一个节点的距离,会根据网络负载情况、内容的可用性、设备工作状况等实时变化,所以这种"最近"的关系是动态变动的。

但上面这套思路会带来一个严重的维护问题:如果同一个系统被部署到不同位置,我们就需要同时部署和维护不同位置的多个系统,系统间协作成本、部署维护成本都会很高。因此在实际生产中,通常的做法是把图片、视频、附件这类流量消耗大、又不经常改变的静态资源部署到互联网的多个位置,而核心系统只部署在一个位置。这就构成了我们常见的内容分发网络(Content Delivery Network,简称 CDN)。

内容分发网络的结构

内容分发网络的组成如图 2所示。在 CDN 中,部署核心系统的节点被称为源站,它是所有静态、动态信息的来源;而部署图片、视频、附件等静态资源的节点,叫作 CDN 节点、缓存节点或者边缘节点。

内容分发网络示意图
图 2:内容分发网络示意图

边缘节点是相对于复杂的网络结构提出的一个概念,它是指与接入用户之间具有较少中间环节的网络节点。因此,相比于源站,用户请求到达边缘节点的网络延迟更小。

当用户请求边缘节点的内容时,边缘节点会先判断自身是否已经缓存了用户要请求的内容。如果该内容已经缓存,边缘节点就直接把内容返回给用户;如果尚未缓存,边缘节点会去源站请求内容再发给用户,并且还会根据设置决定是否在自身也缓存一份。所以,边缘节点中存储的只是源站中部分内容的备份。

边缘节点(也就是 CDN 节点)的数目,对内容分发网络的效率有较大的影响。节点数目越多,用户与最近的 CDN 节点之间的中间环节越少,通讯时延也就越小。但在互联网上部署众多 CDN 节点需要极大的成本,因此 CDN 节点多由专门的 CDN 服务商部署并对外提供服务。

内容分发网络有以下几个优点:

  • 减小了系统并发数。系统不再是网络上的一个节点,而是多个节点,每个系统只承担一部分请求,减少了各自的并发数。
  • 减少了平均响应时间。用户请求会被分配到最近的节点上,减小了网络延迟,也就缩短了平均响应时间。
  • 减少了网络拥堵。每个用户的请求都被分配到最近的节点上,无须经过骨干网络,减轻了对骨干网络的压力。

不过 CDN 节点中只能缓存静态内容,一些涉及动态内容的请求仍然需要源站处理。通常我们会通过 CDN 控制中心为各个 CDN 节点配置规则列表,节点会根据规则对请求内容进行分类:

  • 对于静态内容:CDN 节点从源站获取到该内容后,会在自身缓存一定的时间;之后再次收到针对同样内容的请求时,直接返回缓存内容。
  • 对于动态内容:CDN 节点不做缓存,而是直接将请求转交给源站处理。

内容分发网络为源站分担了大量静态资源请求,降低了源站的并发请求数,使得同样软硬件配置的源站可以承担更多的外部并发。

内容分发网络的原理

调用方请求一个服务时给出的目的地址是源站的地址,对应网络中源站所在的节点。那么 CDN 是如何把指向源站地址的请求,分散到不同 CDN 节点上的呢?这是 CDN 要解决的一个核心问题,也就是把发往源站的请求拦截给 CDN 节点。这一过程,和域名解析有关。

域名解析,就是把域名解析为 IP 地址的过程。IP 地址标志了网络中一个节点的位置,通过它可以在网络中寻址找到对应节点,例如"185.199.108.153"就是一个 IP 地址;域名则是为了让 IP 地址更容易被记住而设的代称,例如"yeecode.top"就是一个网站域名。

域名解析由域名系统(Domain Name System,简称 DNS)来完成,可以把它看作一个保存了域名和 IP 地址对应关系的数据库;而域名解析,就是从这个数据库中查找某个域名对应 IP 地址的过程。

域名和 IP 地址的对应关系记录叫作 A 记录。域名系统不仅能存 A 记录,还能存多种其他记录类型,如 MX 记录、CNAME 记录、NS 记录、TXT 记录等。其中最常用的,是 A 记录和 CNAME 记录。

  • A 记录:最常用的记录类型,记录了域名和 IP 地址的对应关系,可把一个域名转为 IP 地址,例如把"yeecode.top"转为"185.199.108.153"。
  • CNAME 记录:也叫别名记录,记录了域名和域名的对应关系,可把一个域名转为另一个域名,例如把"yeecode.github.io"转为"yeecode.top"。

我们可以通过域名解析服务商向域名系统中写入相关域名的记录,图 3展示了某域名解析服务商提供的域名记录管理界面。图里所示的设置,可以把"example.yeecode.org"用 A 记录转发到某 IP 地址,把"www.yeecode.org"和"yeecode.org"用 CNAME 转发到"yeecode.top"。

域名记录管理界面
图 3:域名记录管理界面

CDN 要把指向源站的请求分散到各个节点上,也就是说需要把一个域名解析成多个 IP 地址。要理解这如何实现,得先了解域名解析的细节。

域名记录并不是存放在一个域名服务器上的,而是以分布式集群的形式存放在多个域名服务器上,这些域名服务器的组成结构如图 4所示。处在最顶端的是根域名服务器,全世界一共有 13 台。

域名服务器结构图
图 4:域名服务器结构图

域名解析是一个递归查找的过程。用户访问某个域名(以"yeecode.top"为例)时,先向 TCP/IP 中设置的首选 DNS 服务器查询对应的 IP 地址,这个 DNS 服务器也叫作本地 DNS 服务器(Local DNS)。如果本地 DNS 服务器恰好负责管理该记录或缓存有该记录,就直接把结果 IP 返回给用户,解析结束;如果没有记录,本地 DNS 服务器会把请求转发给根 DNS 服务器,根 DNS 服务器判断该地址的顶级域名(即".top")由哪台顶级域名 DNS 服务器负责,并转发过去。顶级域名 DNS 服务器如果有记录就解析,没有则继续转发给下一级 DNS 服务器。最终,找到负责管理该域名的 DNS 服务器,由它完成解析并给出一个 IP 地址。可见,经过层层指派后,最终负责管理该域名的 DNS 服务器,拥有这个域名的最终解析权。

在使用 CDN 时,需要用 CNAME 将源站域名指向 CDN 服务商指定的域名,而后者的解析由 CDN 服务商的 DNS 服务器负责。于是,源站域名的最终解析权就交到了 CDN 服务商提供的 DNS 服务器手中。

CDN 服务商的 DNS 服务器并不会简单地给出一个固定 IP 地址,而是会根据用户请求的源 IP 等信息,找出一个距离当前用户最近的 CDN 节点 IP 后返回给用户。这样一来,用户解析的是源站的域名,拿到的却是 CDN 节点的地址。

之后,用户请求便前往该 CDN 节点获取内容。CDN 节点再分析用户请求:如果是静态资源请求,就直接返回;如果是动态资源请求,就转发给源站处理。

图 5展示了使用内容分发网络时的域名解析过程。

内容分发网络的工作原理
图 5:内容分发网络的工作原理

经过 CDN 服务商的处理,网络上众多指向源站的请求,实际已经被分散到了不同的 CDN 节点上。而对用户而言,这一切是无法感知的,他们总感觉自己在访问同一个域名。

现实中,众多网站都使用 CDN 服务商的服务,为自身网站的静态资源建立缓存。因此我们浏览网站时拿到的静态资源,多是从 CDN 节点上直接获取的。

内容分发网络的局限性也是明显的:它只能缓存静态内容,不能缓存动态内容。对动态内容的请求最终还是要落到源站处理,如果源站的动态请求过多,则需要通过其他策略对请求进行分流。


在 AI 编程迅猛发展的今天,编码能力逐步弱化,而架构能力则成了开发者更核心的竞争力。聊完内容分发网络和它背后的域名解析原理,如果你对"怎么把高并发系统的流量分发出去"这类架构问题感兴趣,推荐一本书《高性能架构之道(第二版)》。

这是一本理论联系实际的架构书,系统讲了怎么从顶层把软件架构好:覆盖分布式、并发编程、数据库调优、缓存、IO、高可用、前端性能优化等众多知识,最后还拿一个真实项目完整走了一遍架构全过程,把书里的方法真正落了地。

高性能架构之道(第二版)

《高性能架构之道(第二版)》

这本书还在台湾地区出了繁体版,叫《巨型服务架构》——繁体版嘛,贵得有点离谱。

就先聊到这儿。

我是软件架构师易哥。可以关注我,我会偶尔冒个泡,分享点编程干货!

可以访问个人知乎阅读更多文章:易哥(https://www.zhihu.com/people/yeecode),欢迎关注。

作者书籍推荐

作者书籍推荐 作者书籍推荐