当前位置: 首页 > 科技观察

什么是CDN?使用CDN一定比不使用它更快吗?

时间:2023-03-16 15:08:46 科技观察

对于开发同学来说,CDN这个词既熟悉又陌生。我在做开发的时候很少用到这个,但总能听到别人提起。我们都听说过它可以加速,大概知道原因,但我们问得更深。使用CDN一定比不使用它更快吗?我感到有点困惑。不过没关系,今天我们就换个角度重新认识一下CDN。什么是CDN?对于数字和文本数据,例如与姓名和电话号码相关的信息。我们需要一个地方来存放它。我们通常使用mysql数据库来保存。文本存储在mysql中。当我们需要再次取出这条数据时,我们需要读取mysql数据库。但是因为mysql的数据是存储在磁盘上的,单实例的读性能差不多5kqps,已经很不错了。好像还可以,但是对于稍微大一点的系统来说,就有点急了。为了提高性能,我们在mysql之前加了一层内存作为缓存层,比如常说的redis,先在内存中读取数据,读取不到再在mysql中读取,这样就大大降低了读取mysql的次数。有了这套组合拳,读取性能轻松达到上万qps。mysql、redis都行,到此为止,说的都是平时比较容易接触到的开发场景。但是如果我现在要处理的不再是上面说的文本数据,而是图像数据。例如,我有一张帅气的照片。只是下面的一个。每次刷到某个声音,听到有人翻蔡健雅的《??letting go??》,就忍不住想发这张图。并配文“我还是忘不了”。那么问题来了。这个图像数据应该存在哪里?,我应该在哪里阅读?我们回过头来看看mysql和redis的场景,无非就是存储层加缓存层。存储层和缓存层对于图片等文件对象,存储层不太可能再用mysql,应该改用专业的对象存储,比如Amazon的S3(AmazonSimpleStorageService,注意是S开头的三个字最后,所谓的s3),或者阿里云的oss(对象存储服务)。对于后面的内容,我们将使用比较常见的oss来进行讲解。至于缓存层,不能再用redis了,需要改用CDN(ContentDeliveryNetwork,内容分发网络)。CDN可以简单理解为对象存储对应的缓存层。CDN和OSS现在可以回答上述问题。对于用户来说,这个图片数据存在对象存储中,需要的时候会从CDN中读取。CDN的工作原理现在我们有了CDN和对象存储,让我们看看它们如何协同工作。对于我们平时看到的图片,我们可以右键复制查看其网址。1667103075060会发现图片的网址是这样的https://cdn.xiaobaidebug.top/1667106197000.png前面的cdn.xiaobaidebug.top是加速域名,后面的1667106197000.png是图片的路径名。当我们在浏览器中输入这个网址时,就会发起一个HTTPGET请求,然后经过下面的流程。CDN查询流程第一阶段:您的电脑首先会通过DNS协议获取域名cdn.xiaobaidebug.top对应的IP。?step1和step2:先查看浏览器缓存,再查看操作系统中的/etc/hosts缓存。如果没有,它会询问最近的DNS服务器(比如你房间里的家用路由器)。最近的DNS服务器上是否有对应的缓存,有则返回。?step3:如果最近的DNS服务器上没有对应的缓存,则查询根域、一级域、二级域、三级域服务器。?step4:然后,最近的DNS服务器会得到这个cdn.xiaobaidebug.top域名的别名(CNAME),比如cdn.xiaobaidebug.top.w.kunlunaq.com。?kunlunaq.com是阿里CDN专用的DNS调度系统。?step5到step7:这时候离你最近的DNS服务器会请求这个kunlunaq.com,然后返回一个离你最近的IP地址给你。第二阶段:对应上图中的step8。浏览器使用这个IP访问CDN节点,然后CDN节点返回数据。在上面的第一阶段过程中,提到了很多新名词,比如CNAME、根域、一级域等,在之前的《DNS有哪些值得学习的优秀设计》中有详细的描述,如果你不明白,你可以阅读它。我们知道DNS的目的是通过域名获取IP地址。但这只是其众多功能之一。DNS报文有多种类型,其中A类是使用域名查询域名对应的IP地址。CNAME类型是使用域名来检查域名的别名。对于普通域名,经过DNS解析后,可以直接得到该域名对应的IP地址(也称为A类记录,A指Address)。例如,下面,我使用dig命令进行DNS请求并打印过程数据。$dig+tracexiaobaidebug.top;;答案部分:xiaobaidebug.top。600INA47.102.221.141可以看到xiaobaidebug.top直接解析得到对应的IP地址47.102.221.141。但是对于cdn域名,经过一波查询,首先得到的是一个CNAME记录xx.kunlunaq.com,然后挖掘这个xx.kunlunaq.com得到对应的一个IP地址。$dig+tracecdn.xiaobaidebug.topcdn.xiaobaidebug.top.600CNAMEcdn.xiaobaidebug.top.w.kunlunaq.com.$dig+tracecdn.xiaobaidebug.top.w.kunlunaq.comcdn.xiaobaidebug.top.w300INA122.228.7.243cdn.xiaobaidebug.top.w.kunlunaq.com。300INA122.228.7.241cdn.xiaobaidebug.top.w.kunlunaq.com。300INA122.228.7.244cdn.xiaobaidedebug.top.w.kunlunaq.com。300INA122.228.7.249cdn.xiaobaidebug.top.w.kunlunaq.com。300INA122.228.7.248cdn.xiaobaidebug.top.w.kunlunaq.com。300在122.228。7.242cdn.xiaobaidebug.top.w.kunlunaq.com。300INA122.228.7.250cdn.xiaobaidebug.top.w.kunlunaq.com。300INA122.228.7.251看到这里,问题又来了。为什么添加CNAME这么麻烦?CNAME指向的其实是CDN专用的DNS域名服务器。它只是整个DNS系统中的一个小型DNS域名服务器,看起来和其他域名服务器一样,不起眼。DNS请求也会正常进入这台服务器。但是当请求真正打到它的时候,它的特殊性就体现出来了。当查询请求命中域名服务器时,普通DNS域名服务器返回域名对应的IP部分即可,但CDN专用DNS域名服务器会要求返回“最近的”来自调用者的服务器IP。CDN专用的DNS解析服务器会返回距离最近的CDN节点的IP。你怎么知道哪个服务器IP离调用者最近?可以看到“最近”这个词其实是用双引号括起来的。CDN专用的DNS域名服务器实际上是由CDN提供商提供的。比如阿里云当然知道自己的CDN节点是什么,以及这些CDN服务器当前的负载状态、响应延迟甚至权重,也能知道调用方。来电者的IP地址是什么?可以通过来电者的IP知道它所属的运营商和大概的位置,并根据条件筛选出最适合的CDN服务器。这就是所谓的“最近”。例如。假设距离最近的CDN机房流量较大,响应速度较慢,但??距离较远的服务器能够更好地响应当前请求,按理说可能会选择距离较远的CDN服务器。也就是说,选择的服务器不一定是地理位置最近的,但一定是目前最合适的服务器。什么是回源?上面的图片URL是https://cdn域名/图片地址.png的形式。也就是说,这张图片是通过访问CDN得到的。那么,直接访问对象存储是否可以获取图像数据并显示出来呢?例如像下面这样。https://oss域名/图片地址.png这就像问能不能不用redis直接从mysql读取文本数据显示出来。当然。这就是我对之前发布在博客上的图片所做的。但这成本更高。这里的成本可以指性能成本或通话成本。看看下面的图片。1667101182393可以看到直接请求oss的成本几乎是通过cdn请求oss的两倍。考虑到我家穷,为了让博客取图更快,我就接入了CDN。但是看到这里,问题又来了。在上面的截图中,红框中有一个词叫“回归本源”。什么是回源?当我们访问https://cdn域名/图片地址.png时,请求会打到cdn服务器。但是CDN服务器本质上是一层缓存,不是数据源,对象存储才是数据源。第一次访问CDN获取某张图片时,很有可能CDN中不存在这张图片的数据,因此需要回数据源获取图片数据。然后放到cdn上。下次再次访问CDN,只要缓存没有过期,就可以打缓存直接返回,不需要再次回源。所以访问过程变成如下。1668605964836还有哪些情况会回源?除了上述cdn取不到数据会返回源站外,还有cdn上的缓存过期也会导致源站返回。另外,即使有缓存,缓存不过期,CDN提供的开放接口也可以用来触发主动回源,只是我们很少接触到这个。另外,回源这件事用户是无法感知的,因为用户在阅读图片的时候,只能知道自己有没有看过。同样是读取,又细分为直接从CDN读取,还是CDN回源读取对象存储后返回。直接带缓存回源和不带缓存回源是有区别的。那么,我们有没有办法判断是否发生了回源呢?有。我们往下看。如何判断是否回源我们以某云的对象存储和CDN为例。假设我要请求下图https://cdn.xiaobaidebug.top/image/image-20220404094549469.png为了更方便的查看响应数据的http头,我们可以使用postman。使用GET方法请求图像数据。然后通过下面的选项卡切换查看响应头信息。检查返回源的响应头的状态。此时查看responseheader下X-Cache的值为MISSTCP_MISS。意思是cachemiss导致CDN回源查oss,拿到数据后返回。那么此时CDN中肯定有这张图片的缓存。我们可以尝试再次执行GET方法来获取图片。1667095186020X-Cache的值变为HITTCP_MEM_HIT,即命中缓存。丽云就是这样做的。其他的,比如腾云,还不错,几乎可以从responseheader中找到相关信息。使用CDN是否比不使用它更快?看到这里我们可以回答文章开头的问题了。如果不访问CDN,直接访问源站,流程如下。更新直接访问源站,但是如果连接了CDN,CDN上没有缓存数据,就会触发回源。更新离开CDN后回源,相当于在原有流程上增加了一层CDN调用流程。也就是说,当使用CDN时,CDN缓存中的未命中导致返回源,这会比不使用时慢。缓存未命中可能是因为CDN中根本就没有这样的数据,也可能是这个数据曾经存在,后来过期了。这两种情况都是正常的,大多数时候不需要任何治疗。但是对于非常罕见的场景,我们可能需要做一些优化。比如你的源站数据有大版本更新,比如更换CDN域名等。上线瞬间,所有用户使用新的CDN域名请求图片。新的CDN节点基本触发100%回源。严重的是,有时它甚至会拖累对象存储。这时候可能需要提前过滤掉热点数据,使用工具预请求一波,让CDN加载热点数据缓存。比如某云上的CDN就有这样一个“刷新预热”的功能。当然CDN刷新预热也可以通过灰度模式进行释放,先让小部分用户体验新功能,让这些用户对CDN进行“预热”,然后逐步释放流量。另外,以前有这个数据,后来过期了。对于热点数据,可以适当增加CDN数据的缓存时间。1667344813600CDN什么时候不能用?从上面的描述来看,CDN最大的优势就是对于来自世界各地的用户,可以就近分配CDN节点获取数据,并且在重复获取同一个文件数据时,起到缓存加速的作用。这非常适合网页图片等场景。因为底层使用的是对象存储,也就是说只要是文件对象,比如视频,都可以通过这个过程访问CDN进行加速。比如我平时用的某个声音和某个手?就是这样做的。然后反过来想,问题就来了。什么时候不应该使用CDN?如果你有公司内网服务,而且该服务请求的图片等文件不太可能被重复调用,此时其实没有必要使用CDN。请注意上面两个加粗的关键点。?内网服务是为了保证你了解服务请求的来源,也能得到对象存储的读权限,如果你的对象存储也在公司内部,大概率已经在同一个计算机房为您服务在这里,它很近。访问CDN也不享受“就近分布CDN节点”的好处。?图片或其他文件不太可能重复使用多次。如果接入CDN,每次去接入CDN获取图片,大概率CDN节点没有你要的数据,相当于每次都需要回去。源到对象存储得到了一把。那么访问CDN就相当于给自己加了一层代理,多一层代理会比较费时。1668612494972关于上面第二点,如果你需要一个明确的指标来说服自己,那么我可以给你一个。从上面的介绍我们知道,通过CDN响应的http头中的X-Cache字段,我们可以看到一个请求是否触发了回源,统计次数,然后除以总数请求的数量。如果得到回源比例,比如回源比例高达90%,那为什么还需要连接CDN呢?总结?对于文本数据,我们习惯使用mysql存储,redis缓存。但是对于文件类型的数据,比如视频图片,需要用oss等做对象存储,用CDN做缓存。?如果使用CDN,它实际上会比不使用时慢。?CDN最大的优势是对于来自世界各地的用户,可以分配CDN节点就近获取数据,在重复获取相同文件数据时,起到缓存加速的作用。如果你的服务和对象存储都在内网,文件数据不太可能被复用,那其实没有必要访问CDN。