CDN缓存是什么
背景
Content Delivery Network
CDN缓存一般是由网站管理员自己部署,为了让他们的网站更容易扩展并获得更好的性能。通常情况下,浏览器先向CDN网关发起Web请求,网关服务器后面对应着一台或多台负载均衡源服务器,会根据它们的负载请求,动态将请求转发到合适的源服务器上。从浏览器角度来看,整个CDN就是一个源服务器,从这个层面来说,浏览器和服务器之间的缓存机制,在这种架构下同样适用。
用户web访问流程
用户向浏览器输入www.web.com这个域名,浏览器第一次发现本地没有dns缓存,则向网站的DNS服务器请求;
网站的DNS域名解析器设置了CNAME,指向了www.web.51cdn.com,请求指向了CDN网络中的智能DNS负载均衡系统;
智能DNS负载均衡系统解析域名,把对用户响应速度最快的IP节点返回给用户;
用户向该IP节点(CDN服务器)发出请求;
由于是第一次访问,CDN服务器会向原web站点请求,并缓存内容;
请求结果发给用户。
CDN的缓存机制
CDN边缘节点缓存策略因服务商不同而不同,但一般都会遵循http标准协议。
通过http响应头中的Cache-control: max-age的字段来设置CDN边缘节点数据缓存时间。
当客户端向CDN节点请求数据时,CDN节点会判断缓存数据是否过期,若缓存数据并没有过期,则直接将缓存数据返回给客户端;否则,CDN节点就会向源站发出回源请求,从源站拉取最新数据,更新本地缓存,并将最新数据返回给客户端。所以,如果我们修改了内容,最好加个版本号,让CDN重新获取资源,从而减少不必要的麻烦。
CDN服务商一般会提供基于文件后缀、目录多个维度来指定CDN缓存时间,为用户提供更精细化的缓存管理。CDN缓存时间会对“回源率”产生直接的影响。若CDN缓存时间较短,CDN边缘节点上的数据会经常失效,导致频繁回源,增加了源站的负载,同时也增大的访问延时;若CDN缓存时间太长,会带来数据更新时间慢的问题。开发者需要增对特定的业务,来做特定的数据缓存时间管理。
CDN的问题
CDN的分流作用不仅减少了用户的访问延时,也减少了源站的负载。但其缺点主要是缓存的同步问题:当网站更新时,如果CDN节点上数据没有及时更新,即便用户再浏览器使用Ctrl +F5的方式使浏览器端的缓存失效,也会因为CDN边缘节点没有同步最新数据而导致用户访问异常。
如何解决CDN的问题
CDN的主要问题是由于缓存同步不及时带来的,缓存更新有两种方式:
定制缓存策略静态文件在返回时由源服务器控制expires、cache-control等属性来定义CDN的缓存策略。
源服务器资源更新时,主动刷新CDN缓存CDN边缘节点对开发者是透明的,相比于浏览器Ctrl+F5的强制刷新来使浏览器本地缓存失效,开发者可以通过CDN服务商提供的“刷新缓存”接口来达到清理CDN边缘节点缓存的目的。这样开发者在更新数据后,可以使用“刷新缓存”功能来强制CDN节点上的数据缓存过期,保证客户端在访问时,拉取到最新的数据。
cdn缓存相关设置
http.Cache-Control:
在 HTTP 1.1 中引入,用于为 Web 发布者提供对其内容的更多控制权,并解决
Expires
标头的局限性。如果同时定义了
Expires
和Cache-Control
标头,则将替代前一个标头。
Expires:
HTTP 1.0 中引入的旧标头支持向后兼容性。
使用基于日期的过期时间,精确到秒。
类似于
Cache-Control: max-age
。当
Cache-Control
不存在时使用。
Pragma:
Azure CDN 默认情况下未采用。
HTTP 1.0 中引入的旧标头支持向后兼容性。
用作具有以下指令的客户端请求标头:
no-cache
。 此指令指示服务器提供新的资源版本。Pragma: no-cache
等效于Cache-Control: no-cache
。
验证
当缓存过时时,使用 HTTP 缓存验证程序将文件的缓存版本与源服务器上的版本进行比较。
ETag:
ETag
为每个文件和文件版本定义唯一字符串。 例如,ETag: "17f0ddd99ed5bbe4edffdd6496d7131f"
。在 HTTP 1.1 中引入,并且比
Last-Modified
更新。 当很难确定上次修改日期时,会非常有用。支持强验证和弱验证,不过,Azure CDN 仅支持强验证。 对于强验证,两种资源表示形式的每个字节都必须相同。
缓存通过在请求中发送带有一个或多个
ETag
验证程序的If-None-Match
标头来验证使用ETag
的文件。 例如,If-None-Match: "17f0ddd99ed5bbe4edffdd6496d7131f"
。 如果服务器的版本与列表中的ETag
验证程序相匹配,则在其响应中发送状态代码 304(未修改)。 如果版本不同,则服务器响应状态代码 200(确定)和更新后的资源。
Last-Modified:
如果
ETag
不是 HTTP 响应的一部分,则使用Last-Modified
。指定源服务器已确定上次修改资源的日期和时间。 例如,
Last-Modified: Thu, 19 Oct 2017 09:28:00 GMT
。缓存通过在请求中发送带有日期和时间的
If-Modified-Since
标头来验证使用Last-Modified
的文件。 源服务器将该日期与最新资源的Last-Modified
标头进行比较。 如果自指定时间以来未修改该资源,则服务器在其响应中返回状态代码 304(未修改)。 如果已修改该资源,则服务器返回状态代码 200(确定)和更新后的资源。