作者:winty的帆宝宝
原文地址:https://juejin.cn/post/6944420222757503006
今天下班前忽然发现维护的项目网站打不开了,打开控制台一看,原来是资源请求的响应头设置了2个 access-control-allow-origin 导致的。(我寻思这东西就算设置重了不应该也能覆盖么)
image.png
image.png
image.png
解决完问题后,我有了以下疑惑:
下面我们就带着问题进行探索。Let's Go~
image.png
image.png
上面做了个小实验,设置了2个类型相同的 key,content-type;它们唯一不同的大小写。可以看到结果,只保留了一个key,value值被拼接起来了。
在以前,人们用IP进行互访,后来发现IP太多不好记忆,便有了域名,比如 www.baidu.com,你一看就知道是百度搜索引擎,而不需要管他的服务器IP是多少,但是在最开始通信的时候,电脑路由器不认识域名,只认得IP啊,要怎么去获得对应的IP呢,这时候有了域名解析,就是去请求网络上的DNS服务器,让他们来告诉你这个域名对应的IP是多少。
常见的DNS解析服务商有:阿里云解析,万网解析,DNSPod,新网解析,Route53(AWS),Dyn,Cloudflare等。
image.png
cdn加速前,域名解析过程如下:浏览器dns缓存 -> 系统dns缓存(Hosts文件) -> 路由器dns缓存 -> 本地DNS服务器(ISP运营服务提供商) -> 本地DNS服务器请求根域名服务器(13个,不是只有13台服务器,分布在世界各地),拿到dns记录 -> 本地DNS服务器根据拿到顶级域名服务器的ip,去请求顶级域名服务器(如.com顶级域名服务器) -> 本地DNS服务器根据拿到二级域名服务器的ip,去请求二级域名服务器 -> …… -> 直到X级域名服务器返回我们目标域名对应的ip地址后,本地DNS服务器缓存该dns记录,然后返回路由器 -> ……(层层缓存后,返回dns记录结果) -> 我们的客户端拿到ip地址,利用该ip地址,封装并发起http/http2请求。
备注:前面4个是递归查询,一旦缓存可用,就直接返回,不会再进行后续步骤,后面是迭代查询,最终获取ip地址,才会返回。
不使用cdn时,利用ip发起请求的过程,如广州的用户要请求一个在北京的 IP 地址,过程如下: 广州用户 -> 广州服务器 -> 湖南服务器 -> 湖北服务器 -> 北京服务器
这样传递数据,就很浪费时间,那如果广州服务器就缓存了数据或资源呢,那不就可以就近获取了。这便是cdn的部分策略了。
备注:TLD,意为顶级域名。 域名层级如下图:
image.png
CDN概念
CDN(Content Delivery Network,内容分发网络)是构建在现有互联网基础之上的一层智能虚拟网络,通过在网络各处部署节点服务器,实现将源站内容分发至所有CDN节点,使用户可以就近获得所需的内容。 简单的说,CDN的工作原理就是将您源站的资源缓存到位于全球各地的CDN节点上,用户请求资源时,就近返回节点上缓存的资源,而不需要每个用户的请求都回您的源站获取,避免网络拥塞、缓解源站压力,保证用户访问资源的速度和体验。
CDN的优点如下:
备注:第3~5点详见参考链接[4],第6点举个例子,热点内容的服务器都在北京,如果我想获取热点内容,我就需要发送请求到北京的服务器,但若有了cdn,我只需要就近服务器获取热点内容,这样就分摊优化热点内容的分布了。
CDN节点缓存策略
CDN通过在现有网络中增加一层新的缓存节点,将源站的资源发布到最接近用户的网络节点,使得客户端在请求时直接访问到就近的CDN节点并命中该资源,减少回源情况,提高网站访问速度。 CDN缓存节点可分为L1节点(一级节点)和L2节点(二级节点),请求的流程是:客户端-->CDN_L1-->CDN_L2-->源站。CDN的L1节点分布在全国各省市,L2节点分布在几个大区下,可以把L2节点理解为汇聚式节点,简单架构如下图所示。
image.png
CDN节点缓存策略如下:
备注:
CDN工作原理
通过以下案例,可以进一步了解CDN的工作原理。 假设加速域名为www.a.com, 接入CDN网络,开始使用加速服务后,当终端用户(北京)发起HTTP请求时,处理流程如下图所示。
image.png
什么资源可以被加速
在HTTP请求的资源,请求可以分为静态请求和动态请求。
备注:(以下为个人见解) 动态请求中,路由优化是指请求路径优化为最短传输路径(不用经过太多服务器);传输优化是指同时部署多个运营商的服务器(比如电信、联通、移动都部署上),避免跨运营商间的请求转换。
CDN的缓存策略
静态内容可以在CDN上缓存多久,这个是根据CDN的缓存策略的。用户通过亚马逊云/阿里云/腾讯云控制台按照文件类型和目录设置缓存时间,针对静态资源配置指定目录和文件后缀名的缓存过期时间和优先级,资源过期后,自动从CDN节点删除。
CDN网络的组成要素
对于普通的Internet用户,每个CDN节点就相当于一个放置在它周围的网站服务器. 通过对dns的接管,用户的请求被透明地指向离他最近的节点,节点中CDN服务器会像网站的原始服务器一样,响应用户的请求。由于它离用户更近,因而响应时间必然更快。
image.png
从上面图中 虚线圈起来的那块,就是CDN层,这层是位于 用户端 和 站点服务器群 之间。
A记录:解析域名到IP
A记录,即Address记录,它并不是一个IP或者一个域名,我们可以把它理解为一种指向关系:域名 www.xx.com → 222.222.222.222 也就是当你访问这些域名或者主机名的时候,DNS服务器上会通过A记录会帮你解析出相应的IP地址,以达到后续访问目的。 所以A记录是IP解析,直接将域名或主机名指向某个IP。
CNAME:解析域名到另外一个域名
CNAME记录,也叫别名记录,相当于给A记录中的域名起个小名儿,比如www.xx.com的小名儿就叫www.yy.com好了,然后CNAME记录也和A记录一样,是一种指向关系,把小名儿www.yy.com指向了www.xx.com,然后通过A记录,www.xx.com又指向了对应的IP:www.yy.com → www.xx.com → 111.111.111.111 这样一来就能通过它的小名儿直接访问111.111.111.111了。
这时候有人问:这不多了一步嘛,不嫌麻烦?
假如这个时候我又想给原域名取几个小名儿,分别叫www.cc.com和www.kk.com那么存在下列指向关系: www.yy.com → www.xx.com → 111.111.111.111 www.cc.com → www.xx.com → 111.111.111.111 www.kk.com → www.xx.com → 111.111.111.111
突然服务器的IP地址因为一些不可描述的原因要换了,不再是111.111.111.111了,换成了333.333.333.333,这时候你发现,只要把www.xx.com的指向修改一下即可: 域名 www.xx.com → 333.333.333.333
这时候你又发现了,原来他的小名儿不需要做更改,直接就能访问服务器,因为他们都只指向了www.xx.com,服务器IP改动与否,它们不管。
那么假如不用CNAME,直接做A记录会怎样? www.yy.com → 111.111.111.111 www.cc.com → 111.111.111.111 www.xx.com → 111.111.111.111 www.kk.com → 111.111.111.111 那么当111.111.111.111更改的时候,全部相关A记录指向关系都要做更改,这时会很麻烦。
CNAME的应用
比较多的是用在CDN加速上。 举个例子:假如你公司中的一台IP为1.1.1.1的服务器,注册了域名为www.dd.com,要对外提供客户访问。随着公司越做越大,访问量也越来越多,服务器顶不住了,你去找CDN提供商购买CDN加速服务,这个时候他们要求你的域名做个CNAME指向他们给你的一个域名叫www.xdd.com,当用户访问www.dd.com的时候,本地DNS会获得CDN提供的CNAME域名:www.xdd.com,然后再次向DNS调度系统发出请求,通过DNS调度系统的智能分析,把这个www.xdd.com指向一个(离用户最近的)CDN提供商的服务器IP,让用户就近取到想要的资源(如访问网站),这样就可以大大降低了延迟。
回源
当 cdn 缓存服务器中没有符合客户端要求的资源的时候,缓存服务器会请求上一级缓存服务器,以此类推,直到获取到,如果最后还是没有,就会回到我们自己的服务器(简称源站)去获取资源。
回源的时机:
回源host
回源host:回源host决定回源请求访问到源站上的具体某个站点。
例子1:源站是域名源站为www.a.com, 回源host为www.b.com, 那么实际回源是请求到 www.a.com 解析到的IP, 对应的主机上的站点www.b.com
例子2:源站是IP源站为1.1.1.1, 回源host为www.b.com,那么实际回源的是1.1.1.1对应的主机上的站点 www.b.com
协议回源
指回源时使用的协议和客户端访问资源时的协议保持一致,即如果客户端使用 HTTPS 方式请求资源,当CDN节点上未缓存该资源时,节点会使用相同的 HTTPS 方式回源获取资源;同理如果客户端使用 HTTP 协议的请求,CDN节点回源时也使用HTTP协议。
TTL
TTL,Time-To-Live,意思为一条域名解析记录在DNS服务器中的存留时间。当各地的DNS服务器接受到解析请求时,就会向域名指定的NS服务器(NS,Name Server,名称服务器,DNS是最著名的NS服务器)发出解析请求从而获得解析记录;在获得这个记录之后,记录会在DNS服务器中保存一段时间,这段时间内如果再接到这个域名的解析请求,DNS服务器将不再向NS服务器发出请求,而是直接返回刚才获得的记录;而这个记录在DNS服务器上保留的时间,就是TTL值。
TTL的数值应该如何设置?
边缘节点
边缘节点,指距离最终用户接入具有较少的中间环节的网络节点。
CDN 调度策略
CDN 调度是指通过各种策略将客户端请求调度到合理的目标机房。以达到成本、质量(可用性、平均速度)的最佳控制。
调度形式一般有以下几种:
DNS 调度
基于请求端 local DNS 的出口 IP 归属地以及运营商的 DNS 调度。
DNS 调度的问题:
HTTP DNS 调度
客户端请求固定的 HTTP DNS 地址,根据返回获取解析结果。可以提高解析的准确性(不像DNS调度,只能通过local DNS IP来做决策),能很好的避免劫持等问题。
当然这种模式也有一些问题,例如客户端每次加载URL都可能产生一次HTTP DNS查询,这就对性能和网络接入要求很高。
302调度
基于客户端 IP 和 302 调度集群进行实时的流量调度。
我们来看一个例子:
302 调度的优势:
302 调度的劣势:
AnyCast BGP路由调度
基于 BGP AnyCast 路由策略,只提供极少的对外 IP,路由策略可以很快的调整。
目前 AWS CloudFront、CloudFlare 都使用了这种方式,在路由层面进行调度。
这种方式可以很好地抵御 DDOS 攻击,降低网络拥塞。
当然这种方式的成本和方案设计都比较复杂,所以国内的 CDN 目前还都是用 UniCast 的方式。
除了静态资源,API 是否可以缓存?
动态加速的对象是动态生成的网页,动态加速一般是对针对内容(如数据库信息等)在用户与- 源站之间建立高速通道,通过路由优化、TCP加速等技术手段对动态内容进行加速,降低节点到源站之间的时延,从而大大降低了用户访问动态网页的延迟。
其实这个问题我没有找到比较合适的解答,以下是个人见解: 我们使用 cdn 的原因是,我们经常有一些比较频繁请求且容量比较大的文件,并且更新频率不那么高的文件。这些文件如果我们都放在自己的服务器上,对于客户端,问题在于延长访问时间;对于服务器端是占用服务器端的资源。所以我们采用分布式的方式扔在 cdn 上。 但是 API请求不同,
所以 API 是不适合放在 cdn 上的。但是如果你的内容是相对静态的,不涉及和用户信息关联,更新不频繁,那么勉强可以考虑用cdn加速,如配置信息(但最好不要)。
资源的过期如何判定?cdn 是如何更新数据的?
资源过期时间就是请求/响应头部来判定(详情请自行搜索 强缓存和协商缓存 等关键词)。
那么 cdn 是如何更新数据的?
不同运营商宽带如何实现互相访问的?
通过BGP Peering(对等)等方式实现流量交换(相互访问),如两家运营商约定在特定地点(互联网交换点)集中进行流量交换。
所以如果你的运营商是电信,可以直接通过电信服务器访问你的目标IP,不需要经过交换转换,那肯定能大幅提高访问速度,当然还要看其他限制原因,如本市的电信,还是跨省的电信。
参考链接: