用CDN一定比不用快吗?

大数据轻松入门:玩Flink创建湖仓和集成架构

download:https://www.51xuebc.com/thread-521-1-1.html

对于开发生来说,CDN这个词既熟悉又陌生。

从事开发的你很少需要接触这个,但总能听到别人提起。

我们都听说过它可以加快速度,我们可能知道为什么,但我们更深入。

用CDN一定比不用快吗?

我觉得有点傻。不过没关系。今天,我们从另一个角度来认识一下CDN。

什么是CDN?

用于数字和文本数据,如与姓名和电话号码相关的信息。我们需要一个地方来存放它。

我们一般用mysql数据库来存储。

当我们需要检索这些数据时,我们需要读取mysql数据库。

但是由于mysql的数据存在于磁盘上,单个实例的读取性能几乎是5kqps,相当不错了。

看起来还行,但是对于稍微大一点的系统来说,就有点着急了。

为了提高性能,我们在mysql之前再加一层内存作为缓存层,比如常说的redis。在读取数据时,优先选择在内存中读取,只有在无法读取时,才能在mysql中读取,大大减少了读取mysql的次数。有了这个组合拳,阅读性能轻松到几万qp。

好了,到目前为止,我们说的都是平时容易接触到的开发场景。

但是现在我要处理的不再是上面提到的文字数据,而是图片数据。

比如我有一张很帅的照片。就下面这个。

每次听到有人翻唱蔡健雅的《放手》,就忍不住想发这张图。

用小品《我还是忘不了》。

那么问题来了。

这个图片数据应该存在哪里?我应该在哪里读呢?

再回到mysql和redis的场景,无非是存储层加缓存层。

对于图片等文件对象,在存储层不太可能再使用mysql,应该改用专业的对象存储,比如亚马逊的s3(注意有三个以S开头的字,所以叫S3)或者阿里云的oss(对象存储服务)。下面的内容,我们就用常见的oss来解释。

而缓存层,不能继续使用redis,需要改用CDN(内容交付网络)。

CDN可以简单理解为对象存储对应的缓存层。

现在你可以回答上面的问题了。对于用户来说,这些图像数据存在于对象存储中,当需要时,将从CDN中读取。

CDN的工作原理

对于CDN和对象存储,现在让我们看看它们是如何工作的。

我们平时看到的图片,可以右键复制查看其网址。

你会发现图片的网址是这样的。

https://cdn.xiaobaidebug.top/1667106197000.png

复制代码

前面的CDN.xiaobaidebug.top是CDN的域名,后面的1667106197000.png是图片的路径名。

当我们在浏览器中输入这个URL时,我们将发起一个HTTP GET请求,然后经历下面的过程。

第一阶段:你的电脑首先会通过DNS协议获取域名cdn.xiaobaidebug.top对应的IP。

步骤1和步骤2:首先检查浏览器缓存,然后查看操作系统中的/etc/hosts缓存。如果没有,你会问最近的DNS服务器(比如你房间的家用路由器)。最近的DNS服务器上有相应的缓存吗?如果有,就退回去。

第三步:如果最近的DNS服务器上没有对应的缓存,则查询根域、一级域、二级域和三级域服务器。

第四步:然后,最近的DNS服务器会得到域名cdn.xiaobaidebug.top的别名(CNAME),比如cdn.xiaobaidebug.top.w.kunlunaq.com。

Kunlunaq.com是阿里CDN专用的DNS调度系统。

第5步到第7步:此时,最近的DNS服务器将请求这个kunlunaq.com,然后返回最近的IP地址给你。

第二阶段:对应上图中的step8。浏览器带着这个IP访问cdn节点,然后cdn节点返回数据。

在上面的第一阶段过程中,提到了许多新术语,如CNAME、根域名、一级域名等。它们在之前的《DNS中有哪些优秀的设计值得学习?不知道的可以看看。

我们知道DNS的目的是通过域名获取IP地址。

但这只是它众多功能中的一个。

DNS报文有很多种类型,其中A类是用域名来查域名对应的IP地址。CNAME类型使用域名来检查该域名的别名。

对于常见的域名,DNS解析后一般可以直接获得域名对应的IP地址(也叫A类记录,A指地址)。

例如,我使用dig命令发出DNS请求并打印进程数据。

$ dig +trace小白debug.top

;;回答部分:

小白汉堡. top . 600 47.102.221.141

复制代码

可以看到xiaobaidebug.top直接解析得到对应的IP地址47.102.221.141。

但对于cdn域名,经过一波查询,第一条记录是xx.kunlunaq.com的一个CNAME,然后再深挖一下,这个xx.kunlunaq.com,就可以得到相应的IP地址。

$ dig +trace cdn.xiaobaidebug.top

名为cdn.xiaobaidebug.top.w.kunlunaq.com。

$挖掘+追踪cdn.xiaobaidebug.top.w.kunlunaq.com

cdn.xiaobaidebug.top.w.kunlunaq.com。300英镑一辆122.228.7.243

cdn.xiaobaidebug.top.w.kunlunaq.com。300英镑一辆122.228.7.241

cdn.xiaobaidebug.top.w.kunlunaq.com。300英镑一辆122.228.7.244

cdn.xiaobaidebug.top.w.kunlunaq.com。300英镑一辆122.228.7.249

cdn.xiaobaidebug.top.w.kunlunaq.com。300英镑一辆122.228.7.248

cdn.xiaobaidebug.top.w.kunlunaq.com。300英镑一辆122.228.7.242

cdn.xiaobaidebug.top.w.kunlunaq.com。300英镑一辆122.228.7.250

cdn.xiaobaidebug.top.w.kunlunaq.com。300英镑一辆122.228.7.251

复制代码

看到这里,问题又来了。

为什么加个CNAME这么麻烦?

CNAME所指的其实是CDN专用的DNS域名服务器。对于整个DNS系统来说,它只是小型DNS域名服务器中的一个,看起来和其他域名服务器没什么两样,平平淡淡。DNS请求也将正常进入此服务器。

但是,当请求真正击中它的时候,它的特殊性就体现出来了。当查询请求进入域名服务器时,普通DNS域名服务器返回域名对应的部分IP就足够了,但是CDN专用的DNS域名服务器会要求返回离调用者“最近”的服务器的IP。

怎么知道哪个服务器IP有最近的调用者?

可以看到“最近”这个词实际上是用双引号括起来的。

CDN的专用DNS域名服务器实际上是由CDN提供商提供的。比如阿里云当然知道自己有哪些CDN节点,以及这些CDN服务器当前的负载情况、响应延迟甚至权重,也能知道调用者的IP地址是什么。它可以通过来电者的IP知道自己所属的运营商及其大概位置,根据条件选择最合适的CDN服务器,也就是所谓的“最近”。

比如说。假设地理位置最近的CDN机房流量较多,响应较慢,但地理位置较远的服务器可以更好地响应当前请求,按理说可能会选择地理位置较远的CDN服务器。

也就是说,选择的服务器不一定是地理上最近的,但一定是目前最合适的服务器。

背后的源头是什么?

上面的图片网址是https://cdn域名/图片address.png的形式。

也就是说这张图是通过访问CDN获得的。

那么,直接访问对象存储可以得到图片数据并显示出来吗?

像下面这样。

https://OSS域名/图像address.png

复制代码

这就好比问你能不能不用redis直接从mysql读取和显示文本数据。

当然可以。

我之前放在博客里的图片就是这么做的。

但是成本较高。这里的成本可以指性能成本,也可以指通话成本。看下图。

可见直接请求oss的成本几乎是通过cdn请求oss的两倍。考虑到我家境贫寒,也为了让博客更快的获取图片,我连上了CDN。

但是看到这里,问题又来了。

在上面的截图中,红框里有一个词叫“回到源头”。

来源是什么?

当我们访问https://cdn域名/图片address.png时,请求会打到cdn服务器。

但是cdn服务器本质上是一层缓存,不是数据源,对象存储才是数据源。

当你第一次访问cdn获取某张图片时,很大概率cdn中没有这张图片的数据,所以你需要回到数据源获取这张图片数据。然后放到cdn上。下次访问cdn,只要缓存没有过期,就可以直接命中缓存返回,不需要回到源头。

所以参观的过程就变成了如下。

那么回到源头还会发生什么?

除了上面提到的cdn,如果你拿不到数据,它会返回源站,如果cdn上的缓存过期,它也会返回源站。

另外,即使有缓存,而且缓存没有过期,也可以通过cdn提供的开放接口来触发,但是我们很少有机会接触到这个。

另外,回到源头这件事,其实用户是察觉不到的,因为用户在看图片的时候,只能知道自己有没有看过。

也是读取,细分为是直接从cdn读取,还是从源读取对象存储后由cdn返回。

那么,我们有什么办法来判断是否发生了倒源呢?

是的。我们继续往下看。

如何判断是否发生货源回流?

以我们的云对象存储和CDN为例。

假设我要请求下图https://cdn . xiaobaidebug . top/image/image-20220404094549469 . png。

为了更方便的查看响应数据的http头,我们可以使用postman。

通过GET方法请求图像数据。

然后通过下面的标签开关查看响应头信息。

此时响应头下X-Cache的值为MISS TCP_MISS。意思是缓存未命中导致CDN回源检查oss,拿到数据后再返回。

那么这个时候CDN里肯定有这张图的缓存。我们可以尝试再次执行GET方法来获取图片。

X-Cache的值变成HIT TCP_MEM_HIT,也就是命中缓存。

这是某云的做法,其他的,比如腾某云,都是大相径庭。几乎都可以从响应头中找到相关信息。

用CDN一定比不用更快吗?

这里可以回答文章开头的问题。

如果不接入CDN,直接接入源站。过程如下。

但是,如果访问CDN,并且CDN上没有缓存的数据,则会触发回源。

相当于在原有流程上增加了一层CDN调用流程。

也就是使用CDN的时候会比不使用的时候慢,因为CDN缓存丢失,返回源。

如果缓存丢失,可能是cdn中根本没有这样的数据,也可能是有这样的数据但后来过期了。

这两种情况都很正常,大部分时候都不需要治疗。

但是对于极少数场景,我们可能需要做一些优化。比如你的源站数据有大版本更新,就像换了cdn域名什么的。然后在上线的那一刻,用户都是用新的cdn域名请求图片什么的,新的CDN节点基本上100%触发回源。在严重的情况下,它甚至可能会拖累对象存储。这时候你可能需要提前筛选出热数据,用工具提前请求一波,让CDN加载热数据缓存。比如云上的CDN就有这样的“刷新预热”功能。

当然,也可以通过灰度发布的模式,让少部分用户体验新功能,让这些用户“热起来”cdn,然后逐步释放流量。

就是曾经有过这个数据,后来过期了。对于热点数据,可以适当增加cdn数据的缓存时间。

什么情况下不应该使用CDN?

从上面的描述来看,CDN最大的优势是对于来自世界各地的用户来说,可以就近分配CDN节点获取数据,在重复获取相同文件数据时可以加速缓存。

非常适合这种网页图片的场景。因为底层使用的是对象存储,也就是说只要是文件对象,比如视频什么的,都可以用这个进程访问cdn进行加速。比如某音某手的短视频一般就是这么做的。

然后反过来想,问题就来了。

什么情况下不应该使用CDN?

如果你有公司内网服务,服务请求的图片等文件不太可能被重复调用,这个时候其实没必要用CDN。

注意上面两个加粗的要点。

内网服务是为了保证你知道服务请求的来源,还可以获得对象存储的读取权限。而且如果你的对象存储也是公司内部的,很有可能已经和你的服务在同一个机房了,非常近。接入CDN享受不到“就近分布CDN节点”的好处。

图片或其他文件不太可能多次重复使用。如果访问CDN,每次访问CDN获取图片,都有很大概率CDN节点没有你想要的数据,相当于每次都要回去对象库获取一个。那么接入CDN就相当于给自己加了一层代理。多了一层代理,就又多了一层时间。

关于上面第二点,如果你需要一个明确的指标来说服自己,那么我可以给你一个。从上面的介绍我们知道,可以通过cdn响应的http头中的X-Cache字段来看一个请求是否触发了对源的返回,统计次数,然后除以请求总数,得到对源的返回比例。比如,如果回归本源比例高达90%,那我们为什么还要接cdn?

摘要

对于文本数据,我们习惯用mysql做存储,redis做缓存。但如果属于文件数据,比如视频图片,就需要用oss做对象存储,cdn做缓存。

如果使用CDN,实际上会比不使用时慢。

CDN最大的优势在于,对于来自世界各地的用户,可以就近分配CDN节点获取数据,当多次重复获取同一文件数据时,具有缓存加速的功能。如果你的服务和对象存储都在内网,文件数据不太可能被重用,实际上就没有必要访问cdn。

分类: 游戏攻略 标签: 暂无标签

评论

暂无评论数据

暂无评论数据

目录