引论:CDN的各种配置方式及配置原理

2020-03-26

前言

我们在前面的一篇文章已经介绍了CDN的基本原理和基本的配置方式,但是你知道CDN还能够有别的配置方式吗?例如说,对于不方便更改网站裸域名DNS记录的站长来说,如何享受CDN的加速效果呢?我们会揭示还有一种方法——只加速网站中的一部分资.还有,使用CDN一定要自己配置DNS吗?可不可以不配置任何DNS就使用CDN呢?也是可以的,DNS配置仅仅是CDN中比较重要的一环,但是CDN的核心概念是「分发」(Delivery),而DNS仅仅是实现分发的一种方式而已.

什么是静态资源

静态资源,顾名思义其实就是一个网站比较不容易变化的那部分资源,资源就是文件(从网页服务器的角度来说),就是不容易产生变化的那部分文件,比如说有哪些呢?以一个博客网站为例,逐一列举一个博客网站的资源,分析它们的更新频率如何:

首页:首页如果是一个文章列表,那是会随着文章发布的频率变更的,经常更新的博客通常会保持一个星期两篇或两篇以上的文章,那就算是3天一次更新,而不经常更新的博客通常是一个月1次到2次更新,那就算是15天一次更.可以合理地认为首页的更新频率是3天1次.

文章页面:是指具体的文章页面,比如说

https://beyondstars.xyz/posts/cdn-deployment/

就是一篇文章,如果写好之后其实是不太可能会经常去更新它.算它15天1次更新吧.

文章当中出现的图片和其他多媒体文件:文章中出现的图片、声音和视频编辑起来肯定比编辑文字要麻烦,所以不妨认为这些多媒体文件是1个月1次更新的,就是说,假如有这么一个资源文件

https://beyondstars.xyz/demonstration.png

那么当它上传到网站服务器上面了之后几乎就不会再更改了.

样式表文件:一般来说就是.css后缀名的文件,即使是网页设计师,为了方便查看样式表更改后的效果,往往只是会在本地服务器进行测试,而对于一般的站长和作者来说,其实是不太经常更改网站主题的——设计和修改网站主题是很劳心费力的事.样式表文件的更新频率起码可以认为不会比1个月1次更频繁.

脚本文件:一般来说就是.js后缀名的文件,这类文件一般来说是为了实现一些动态的功能,比如说访客日志和流量分析,评论和留言板功能,一些复杂的CSS实现不了或者不方便实现的动画效果等,如同更改和设计样式很繁杂一样,编写程序也是比较费心的事情,所以同样可以认为脚本文件的更新频率不会比1个月1次更频繁.

那么我们可以得到下表

资源类型 更新频率估计 定性
首页(菜单页面) 1个月小于1次 不频繁
首页(文章列表) 平均3天1次 频繁
文章 1个月小于1次 不频繁
样式表 1个月小于1次 不频繁
脚本文件 1个月小于1次 不频繁

参考这个表格,我们对于什么可以被缓存——进而可以被静态资源加速,什么不适合被缓存,算是有了一个基本的概.现在可以认为,菜单页面,文章,样式表和脚本文件原则上是可以被缓存的——进而可以被CDN.

这里我们把「可缓存」和「可CDN」这两个Term联系起来是因为,一般大家使用的都是Pull CDN,当被加速的资源自身有足够长的缓存有效期,才有机会在CDN的边沿服务器中存活足够长的时间,当用户的请求到达边沿服务器时,边沿服务器才能够拿缓存出来作为响应(缓存命中),否则如果缓存过期了CDN边沿服务器就要向源站点再拉取(Pull)最新的资源用来更新缓存(缓存未命中)从而造成用户等待响应的时间增加,说白了在缓存未命中的情况下,使用CDN几乎是没有效果的,可以这么说,Pull CDN的加速效果完全依赖于缓存命中率(每一百次请求中有多少次请求被缓存所响应).

全站加速

回顾前面我们给exploro.one这个网站实现CDN的方式,或者说CDN加速exploro.one的工作机理:我们实际上是为exploro.one配置了「全站加速」,全站加速,就是整个网站,exploro.one下的所有路径,不管是exploro.one/path1还是exploro.one/path1/path2还是exploro.one/,只要CDN边沿服务器认为得到的资源——不管是在哪个路径——是可缓存的,那CDN就会把这个资源缓存起来,以备下一次同样的请求可以拿缓存来响.在这种配置方式下,除了初期配置比较麻烦,后续要想更改缓存配置其实很简单,我们只需编辑/etc/nginx/conf.d/exploro.one.conf配置文件就可以了,CDN那边一次配置就永久运行,不会有额外配.

但是这种配置方式有一点很不方便,它要求我们更改域名的CNAME记录,首先DNS的更改有这么一个生效时间——为了等待旧的DNS缓存的过期以及新的DNS缓存的重建和传播,且不说更改CNAME还要涉及到域名服务商,如果改错了要调试起来也比较麻烦,设想要是我们把CNAME记录指向了错误的域名,从诊断到再次更改还得花时间,或者有的站长根本就没权限更改CNAME记录,或者就是旧的配置不想改,例如beyondstars.xyz这个网站是被CloudFlare自动全站CDN的,如果还要使用CloudCone的CDN功能就要更改裸域名的CNAME记录,就不能再享受CloudFlare的保护.

凡此种种,总有一些原因阻碍我们更改网站域名的CNAME记录——或是外部的或是自身的,我们希望找到一种方式,既不更改网站裸域名的CNAME记录,又得以使网站的打开速度得到提.需要注意的是,前面这种「全站加速」的CDN配置方式,实际上已经实现了「静态资源加速」,因为静态资源确实也被「加速」了,所以可以认为「静态资源加速」是「全站加速」的阉割版实现.

不用配置DNS就启用静态资源加速

CDN的作用之一是加快网站的静态资源的加载速度,而加快网站的静态资源加载速度(静态资源加速)的途径之一,就是让静态资源被分发到离用户比较近的地方,前面我们给exploro.one配置CDN的时候,静态资源加速是通过给exploro.one这个域名设置CNAME实现的,具体地,当有请求发生时,浏览器会向DNS服务器请求exploro.one的地址,然后浏览器总会得到最近的边沿服务器的地址,于是静态资源加速就实现.换句话说,exploro.one全站都实现了静态资源加速,是因为浏览器总是会向所有提供exploro.one的内容的服务器中的最近的那一台发起请求,即在浏览器看来,exploro.one就是对自己来说最近的服务.这提示了我们,任何一个域名,domain1.com也好,domain2.com也好,只要DNS服务器能够返回,比如说,domain1.com所有地址里面离客户最近的服务器的地址,那么domain1.com名下的资源,就是已经实现了静态资源加速的,那么用户请求domain1.com名下任何一个资源时,比如说请求domain1.com/js/main.js时,收到的响应肯定是来自和自己最接近的那台服务器.

说到这里,我们其实已经知道了如何为自己的网站实现部分静态资源加速了,我们假设有两个域名,x.com没启用CDN,也没启用部分静态资源加速,y.com启用了全站加速,y.com就好比前面一篇文章中我们作为例子的exploro.one.现在用户打开x.com的时候,由于有一个资源,比如说x.com/js/main.js`,加载的特别慢,

<script src="/js/main.js" defer></script>

以至于影响到了用户体验,那么我们现在就希望,在不对x.com的DNS设置做任何更改的情况下,加快x.com的打开速度,现在我们已经知道了影响打开速度的瓶颈在/js/main.js这个文件, 我们只要「静态资源加速」/js/main.js这个文件就行了,为了这么做,我们只需把

<script src="/js/main.js" defer></script>

替换为

<script src="https://y.com/js/main.js" defer></script>

并且把x.com服务器上的/js/main.js原样地复制到y.com服务器上的/js/文件夹里面就行了.

这样一来,用户在打开x.com轮到浏览器要加载/js/main.js的时候,浏览器会请求https://y.com/js/main.js这个地址,也就是像y.com请求/js/main.js,由于y.com是全站加速的,即在任何地方查询y.com的地址DNS都会根据查询发起者的地理位置返回最近的地址,所以浏览器最终会向能提供/js/main.js的最近的服务器发起请求,于是单个文件,或者说部分静态资源加速,就这样实现了,而不需要更改任何DNS记.类似地,不仅是main.jsx.com网站上所有的.js文件都能被同样的方式静态加速,而.css文件,甚至任何媒体文件,比如.jpg.png.svg.mp3,所有在HTML网页中以地址的形式表示的资源,通过把地址替换成y.com上相应的地址,都能被静态资源加速.

为了加深印象,我们还是以CloudCone CDN为例,演示一下,如何不变更主域名的DNS设置,就给网站实现部分静态资源加.我们用另外一个示例网站demo.exploro.one来做演示,这个网站是和exploro.one是没有任何关系的.

网站的根目录下有如下文件

index.html
main.css

其中index.html是这样的

<!DOCTYPE html>
<html>
    <head>
        <title>cdn demo</title>
        <link rel="stylesheet" type="text/css" href="main.css">
    </head>
    <body>
        <h1>Greetings!</h1>
        <p>This is a demo site demonstrating partial resources accelerating.</p>
    </body>
</html>

main.css是这样的

h1 {
    background-color: bisque;
}

p {
    background-color: burlywood;
}

这就是我们可爱的示例网站:

用作CDN配置示例的网站展示

用作CDN配置示例的网站展示

接下来进入CloudCone的CDN配置界面,单击Add pull zone,这回不用再想复杂的密码了,直接输入网站主域名,并建议选择HTTPS协议,如图:

Pull Zone直接设置为主域名

Pull Zone直接设置为主域名

接下来可以看到Your pull zones列表下面多出来一行,Origin URL会对应demo.exploro.one,也就是主域名

Pull Zones列表多出来一项

Pull Zones列表多出来一项

点右边这个新的Pull Zone的Manage按钮,再点击左边的Hostnames,可以看到Pull Zone的详细信息

Pull Zone的详细信息

Pull Zone的详细信息

这时由于我们并没有打算设置CNAME记录,所以xxx.r.worldcdn.net那个地址可以忽略掉,我们还看到cxx.r.worldssl.net这个地址右边提示"SSL ON”,就说明这个地址是可以拿来发起HTTPS请求的,可以直接在浏览器里试一下

直接向CDN请求资源

直接向CDN请求资源

直接向CDN请求资源

直接向CDN请求资源

可以看到,不仅仅是main.css,就连主页面index.html都被边沿服务器拉取过去当缓存了,虽然说我们并没有打算加速index.html而只是打算加速main.css.不过这提示这我们,源站,这里我们设置的是demo.exploro.one`,的任何资源,只要是可缓存的,都可被加速,但是我们怎么设置又是另一回事.

现在为了加速main.css这个文件,我们更改index.html,把

<link rel="stylesheet" type="text/css" href="/main.css">

更改为

<link rel="stylesheet" type="text/css" href="http://cmrx8132cc.r.worldssl.net/main.css">

因为我们知道

cmrx8132cc.r.worldssl.net

这个地址是CDN优化过的,在任何地方请求这个地址的资源,都能得到最近服务器的应答.

静态资源成功地被加速

静态资源成功地被加速

可以看到demo.exploro.one这个网站的main.css这个文件就成功地被静态资源加速了,我们没有更改demo.exploro.one这个域名的DNS的任何设.类似地,demo.exploro.one这个网站以后如果还有更多的静态资源,比如说更多的样式表文件,脚本文件,或者图片文件和其他多媒体文件,都可以通过替换资源链接的形式实现静态资源加.要利用现在流行的JSDelivrCDNJS,或者是一些图床,实现网站的静态资源加速,也是类似的方法.

简单易用的CloudFlare

CloudFlare因为配置简单灵活,功能繁多,以及免费,受到了许多站长的青.之所以现在才开始介绍CloudFlare,是因为CloudFlare为了配置上的简便,把许多底层的东西抽象掉了,不便于逐个步骤地演示CDN的工作方式,但是简单地介绍一下CloudFlare还是无妨的.

一个域名被导入到了CloudFlare之后呢,在CloudFlare的DNS设置界面,把那个小云朵☁️点上,CloudFlare就自动地为点亮了小云朵☁️的那个域名提供CDN服务了,这又是怎么做到的呢?毕竟只是点了一下.

我们知道,要把域名导入到CloudFlare的DNS系统,需要在原来的域名服务商那里,把NS服务器地址先改成CloudFlare的Name Server的地址,在那之后,才能够在CloudFlare的界面配置自己的域名的DNS和CDN(之前也可以配置,但之前不是在CloudFlare的界面配置.NS记录保存的地址,实际上就是存储我们这个域名的一系列DNS记录(包括A记录,CNAME记录,MX记录,AAAA记录等)的那台服务器的地址,也就说,自从这个域名的NS记录设置为CloudFlare的域名服务器之后,此后所有对这个域名的查询,都要经过CloudFlare,CloudFlare可以返回任何符合DNS协议的回答,同样地,如果有人在浏览器打开demo.exploro.one这个网站,总会有一个DNS查询请求发送到CloudFlare的DNS服务器,于是CloudFlare的DNS服务器就自动地返回CloudFlare的边沿服务器地址(如果用户点亮了小云朵☁️的话)或者真实地址(用户自己设置的A记录)或者是CNAME的地址(就像是上一节我们为exploro.one设置的那样).

由此我们受到启发:通过配置一个域名的CNAME记录可以实现全站CDN,并且通过配置NS记录也可以,关键的仅仅是,DNS服务器会返回边沿服务器的地址,或者说,会有某种方式使得请求发起者向边沿服务器发起请求,仅此而.CNAME并不是唯一的配置CDN的方式,甚至还有除了配置CNAME记录和NS记录之外的方式实现网站的CDN加速.

技术交流cdndevops

traceroute介绍:原理和实验

CDN部署过程全记录:原理和实践