CDN 原理
CDN
CDN即内容分发网络(Content Delivery Network)的简称,是建立在承载网基础上的虚拟分布式网络,能将源站内容(包括各类动静态资源)智能缓存到全球各节点服务器上。这样不仅方便了用户就近获取内容,提高了资源的访问速度,也分担了原站压力。
加速域名
加速域名指需要使用CDN加速的域名。加速域名也是域名。加速域名一般配置CNAME记录,指向CDN网络节点。普通域名一般配置A记录,指向提供服务的业务服务器。
CNAME记录、A记录和NS记录
DNS(Domain Name System, 域名系统)提供了将域名转换为IP地址的服务。为了完成这个转化工作,DNS的数据库中需要维护相关数据,这些数据被叫做RR(Resource Record,资源记录)。资源记录有很多种类型,比如A、NS、SOA、CNAME 和 PTR记录。
大家接触最多的就是A(Adress)记录。A记录是一条从域名到IP地址的映射记录。而CNAME(Canonical Name)记录是一条从域名到域名的映射记录,它很好的实现的业务域名与CDN系统域名的解藕。简单理解,如果一个域名配置了A记录,DNS就会将它解析成A记录对应的IP地址。如果一个域名配置了CNAME记录,DNS就会将他解析成CNAME记录指定的另外一个域名。A记录和CNAME记录是互斥的,不能同时存在。CDN解析是个非常复杂的过程,详细推荐查看DNS原理及其解析过程
NS(Name Server)记录的是DNS服务器相关的一条记录,它指定该域名应该由哪一台DNS服务器进行解析。一般把通过NS记录制定的DNS服务器叫做该域名的权威DNS服务器。
源站
提供原始资源(使用CDN加速的资源)的业务服务器,可以指定为域名或IP地址。
回源
CDN节点未缓存请求资源或缓存资源已到期时,回源站获取资源,返回给客户端。
工作原理
假设我建立了一个网站,域名为“www.marshall.com”,用户访问的主页链接为“www.marshall.com/idx.html”。为了缓解服务端压力和加快访问速度,决定使用阿里云 CDN 服务。
为了更好地理解工作原理,先了解一下 CDN 的接入流程。
接入流程
主要接入步骤如下:
- 到某域名供应商处申请一个加速域名:“js.marshll.com”。
- 到阿里云 CDN 平台添加加速域名“js.marshll.com”,同时设置其源站域名为“www.marshll.com”
- 阿里云 CDN 平台自动分配一个 CNAME 域名:“js.marshll.com.ali.com”。
- 到域名供应商处给加速域名“js.marshall.com”添加 CNAME 记录,其值为上一步得到的 CNAME 域名:“js.marshall.com.ali.com”。
对以上步骤做进一步说明:
- 为了使用 CDN,必需另外再申请一个加速域名,作为使用 CDN 的入口。
- 加速域名配置的是 CNAME 记录,值为 CDN 平台提供的 CNAME 域名,该 CNAME 域名指向 CDN 系统节点。
- 添加加速域名时需要配置源站域名,据此,CDN 平台保存了加速域名与源站域名的映射关系。
- CNAME 域名的格式一般是:<加速域名> + <供应商主域名>
CDN系统架构
从功能上看,典型的CDN系统由分发服务系统、负载均衡系统和运营管理系统组成。分发服务系统主要负责资源的响应、缓存和同步。负载均衡系统主要负载对用户请求进行调度。运营管理系统则负责运营需求管理和网络系统管理。
从节点分布上看,CDN系统主要分为边缘层和中心层。边缘层分布在CDN网络的边缘位置,给用户提供就近访问服务。中心层则负责完成资源同步和运营管理等功能。
中心层保存了加速域名的相关配置信息,比如源站域名,也缓存了加速域名下的各种资源。在边缘层节点未命中缓存时,需要向中心层节点发起请求。而中心层节点未能命中缓存时,需要查找对应的源站域名,并向该源站域名发起请求,然后再逐层返回并缓存用户请求的资源。
访问流程
当用户第一次访问的流程如下图1所示
需要进一步说明的是:
- 第 1 步访问的是加速域名,而不是源站域名。
- 第 3 步返回 CNAME 域名。
- 第 5 步返回 CNAME 域名对应的 IP 地址,指向 CDN 边缘层节点。
- 第 6 步请求的 URL (或者说 Referer )仍为‘js.marshall.com/idx.html’。
- 第 7 步请求中心层节点时,会带上第 6 步的 URL 作为参数。
- 第 8 步通过查询配置数据得到源站域名,进而向源站发起请求。这里的业务服务器即为 CDN 的源站。简单起见,省略了从 DNS 服务器查询 A 记录的过程。
- 在整个过程中,URL 的域名会变化,但是 URL 的路径不会变化。
需要进一步说明的是:
- 由于本地 DNS 客户端拥有了加速域名的解析缓存,就不需要再查询 DNS 服务器了。
- 由于 CDN 边缘层节点有了对应资源的缓存,就不需要再向上请求资源了。
需要进一步说明的是:
- 由于用户 A 和用户 B 地域相差比较远,使用不同的边缘层节点,所以边缘层节点没有对应资源的缓存,需要向中心层节点请求资源。
- 中心层节点拥有该资源的缓存,所以就不需要回源了。
就近访问原理
CDN系统是如何实现就近访问的呢?
CNAME域名是CDN供应商提供的,CDN供应商拥有对CNAME域名的配置权。CDN供应商会把CNAME域名的NS记录设置为自己搭建的DNS服务器。这样一来,解析 CNAME 域名的时候就会请求 CDN 供应商搭建的 DNS 服务器。而 CDN 供应商在 DNS 服务器中实现了负载均衡,会返回离用户较近的边缘层节点的 IP 地址。如此便实现了就近访问。
CNAME验证
域名“a1.pstatp.com”, “a3.pstatp.com”, “a6.pstatp.com”分别是用于网宿、阿里云和金山云的 CDN 服务的加速域名。用 dig 命令来查看它们的 CNAME 记录,分别为为“a1.pstatp.com.wscdns.com”、“a3.pstatp.com.w.alikunlun.net“和”a6.pstatp.com.download.ks-cdn.com“,与预期相符。
从路径反推源站 IP 地址
我们并不知道源站 IP 地址是多少,因为不是我们配置的。因为在访问过程中路径是不会变的,可以根据路径从 LB(Load Balancing,负载均衡)配置中反推源站 IP。从安全考虑,源站 IP 是保密信息,下面会对敏感信息进行打码。
以https://a3.pstatp.com/inapp/lib/raven.js请求为例子,
通过VIP访问
可以在提供CDN服务的厂商处查询源站的VIP(虚拟IP),然后进行访问。
由于是 VIP,所以必需加上 Host 信息才能访问(VIP 也是保密信息,此处省略),比如
curl -H "Host: a3.pstatp.com" http://x.x.x.x/inapp/lib/raven.js
执行后也是可以成功请求的资源的。
那么什么事VIP呢?我们理解的一般是真实 IP,即一个 IP 地址对应一台电脑。更专业一点说,就是一个 IP 地址对应一个 MAC 地址。IP 地址到 MAC 地址的映射是由ARP协议实现的。VIP不是与某个固定的 MAC 地址映射的,而是与一群 MAC 地址中的某个 MAC 地址映射的。具体指向哪个 MAC 地址根据当时的场景决定。也就是说,VIP 是一个逻辑 IP,而不是实体 IP。VIP 主要是用来实现网络地址转换,网络容错和可移动性,在云和负载均衡技术中有重要的应用。
前端页面部署
前端页面相关的都是静态资源,现在基本都走 CDN。在对前端页面进行部署时,需要上传 CDN。
HTML文件部署
HTML 文件已经被上传到回源服务器上,可以通过 CDN 来访问 HTML 文件了。前端页面部署工作是不是就结束了?显然没这么简单。
CDN 缓存有效地提升了访问速度,但是也带来了文件无法及时更新的问题。一般通过 Hash 字符串的方式来解决这个问题。在每个文件名后面加一个 hash 字符串,每次发布的静态资源的文件名都不一样,相应的访问 URL 也不一样,这样就不会命中缓存。这种方式对 CSS 和 JS 文件很好使,但是对 HTML 文件就不合适了。CSS 和 JS 文件名是写在 HTML 文件中的,文件名的替换由 Webpack 自动完成的。用户访问某个网站时,一般会重定向到主页面。也就是说,HTML 文件名一般是重定向时决定的,需要在重定向的路由中配置,比如 nginx 配置文件,替换工作基本手动完成。每次发布后都需要手动修改 nginx 配置,才能使用户访问最新的 HTML 文件,这显然是不可行的。所以,Hash 字符串的办法不适用于 HTML 文件。
因此,HTML 文件需要另外部署。
与服务端混合部署
早期的一种解决方案是把 HTML 文件放到服务端工程里面,与服务端服务一起部署。服务端服务是一个运行的服务,可以提供对 HTML 文件的访问。每次需要访问新的 HTML 文件时,把服务端工程里面的 HTML 文件替换成新的文件,然后再重启服务就可以了。
混合部署的缺点:
- 发布速度慢,受制于后端服务的发布
- 前后端工程耦合,不利于项目的维护,也不利于部署管理
独立部署
单独给前端页面起一个页面服务,同时提供管理服务来管理这些页面服务。该页面服务只提供访问 HTML 文件的功能,不实现其他业务功能。
独立部署的优点:
- 发布速度快
- 功能聚焦,便于管理