http缓存和cdn缓存
用户第一次访问网站时,浏览器会从服务器获取所有的资源。在传输过程中,浏览器会通过一些约定好的响应头,从而确定是否需要将这个资源保存一份到本地作为缓存,当用户第二次访问该网站的时候,浏览器就会从缓存中加载资源,不用向服务器请求资源,从而提高了网站的访问速度,而若使用了CDN,当浏览器本地缓存的资源过期之后,浏览器不是直接向源站点请求资源,而是向CDN边缘节点请求资源,CDN边缘节点中也存在缓存,若CDN中的缓存也过期,那就由CDN边缘节点向源站点发出回源请求来获取最新资源。 概况起来就是 在CDN加速的情况下,获取资源是先强缓存,再走CDN缓存,最后走协商缓存。
强缓存
不需要发送请求到服务端,直接读取浏览器本地缓存,在 Chrome 的 Network 中显示的 HTTP 状态码是 200 ,在 Chrome 中,强缓存又分为 Disk Cache (存放在硬盘中)和 Memory Cache (存放在内存中),存放的位置是由浏览器控制的。是否强缓存由 Expires、Cache-Control 和 Pragma 3 个 Header 属性共同来控制。
Expires
Expires 的值是一个 HTTP 日期,在浏览器发起请求时,会根据系统时间和 Expires 的值进行比较,如果系统时间超过了 Expires 的值,缓存失效。由于和系统时间进行比较,所以当系统时间和服务器时间不一致的时候,会有缓存有效期不准的问题。Expires 的优先级在三个 Header 属性中是最低的。
Cache-Control
Cache-Control 是 HTTP/1.1 中新增的属性,在请求头和响应头中都可以使用,常用的属性值如有:
max-age:单位是秒,缓存时间计算的方式是距离发起的时间的秒数,超过间隔的秒数缓存失效 no-cache:不使用强缓存,需要与服务器验证缓存是否新鲜 no-store:禁止使用缓存(包括协商缓存),每次都向服务器请求最新的资源 private:专用于个人的缓存,中间代理、CDN 等不能缓存此响应 public:响应可以被中间代理、CDN 等缓存 must-revalidate:在缓存过期前可以使用,过期后必须向服务器验证
Pragma Pragma 只有一个属性值,就是 no-cache ,效果和 Cache-Control 中的 no-cache 一致,不使用强缓存,需要与服务器验证缓存是否新鲜,在 3 个头部属性中的优先级最高。
协商缓存
当浏览器的强缓存失效的时候或者请求头中设置了不走强缓存,并且在请求头中设置了If-Modified-Since 或者 If-None-Match 的时候,会将这两个属性值到服务端去验证是否命中协商缓存,如果命中了协商缓存,会返回 304 状态,加载浏览器缓存,并且响应头会设置 Last-Modified 或者 ETag 属性。
ETag/If-None-Match
ETag/If-None-Match 的值是一串 hash 码,代表的是一个资源的标识符,当服务端的文件变化的时候,它的 hash码会随之改变,通过请求头中的 If-None-Match 和当前文件的 hash 值进行比较,如果相等则表示命中协商缓存。ETag 又有强弱校验之分,如果 hash 码是以 "W/" 开头的一串字符串,说明此时协商缓存的校验是弱校验的,只有服务器上的文件差异(根据 ETag 计算方式来决定)达到能够触发 hash 值后缀变化的时候,才会真正地请求资源,否则返回 304 并加载浏览器缓存。
Last-Modified/If-Modified-Since
Last-Modified/If-Modified-Since 的值代表的是文件的最后修改时间,第一次请求服务端会把资源的最后修改时间放到 Last-Modified 响应头中,第二次发起请求的时候,请求头会带上上一次响应头中的 Last-Modified 的时间,并放到 If-Modified-Since 请求头属性中,服务端根据文件最后一次修改时间和 If-Modified-Since 的值进行比较,如果相等,返回 304 ,并加载浏览器缓存。
在不走CDN情况下他的流程如下:
CDN缓存
cdn缓存是一种服务端缓存,cdn服务商可以将源站上的资源缓到其各地的边缘服务器节点上。当用户访问该资源时,cdn再通过负载均衡将用户的请求调度到最近的缓存节点上,有效减少了链路回源,提高了资源访问效率及可用性,降低带宽消耗。
缓存更新机制
CDN缓存更新主要有两种方式:
超出缓存的过期时间
当CDN节点上的缓存失效后,缓存不会立即被清理,在源站返回last-modified/etag头部情况下,CDN将会回源发起缓存有效性校验(即协商缓存)。 可以通俗地理解为,CDN将之前缓存文件的标识信息带回源站询问是否发生变化。
如源站内容未发生变化,源站将返回304状态码,CDN节点仅更新缓存的有效周期,不变更缓存内容,截止下次缓存时间到期前不会再次回源; 如源站内容发生变化,源站将返回200状态码和更新后的内容,CDN节点将更新缓存的有效周期并覆盖缓存内容,实现文件更新的效果。
主动更新
当CDN节点上的缓存未失效,但源站内容已经发生变化,业务上需要立即更新CDN上资源的缓存时,需要使用CDN的缓存刷新功能,您需要通过 CDN控制台-刷新预热 或者 API接口 下发缓存的刷新任务,详细操作和说明将在下章节为您介绍。
CDN缓存时间主要受两个部分控制:
1: 源站返回的标准HTTP缓存控制头部(cache-control)。 2您在控制台上配置的缓存时间。
CDN节点上的缓存生效优先级如下
- 源站响应pragma:no-cache、cache-control:no-cache(或者no-store,或者max-age=0)时,不缓存。
- CDN控制台设置的缓存过期时间或者状态码过期时间。
- 源站配置其他缓存规则,优先级由高至低为:cache-control>expires>last-modified>etag。
- 源站返回的数据中ETag、last-modified、cache-control和expires这些缓存相关的响应头都没有携带,则默认不缓存。
缓存命中判断
正确配置缓存后,您可以通过访问资源URL时,通过CDN响应头中的X-Cache信息判断是否命中缓存,首次访问时可能会显示MISS,可以通过刷新页面或重试请求检查下次请求是否命中。
X-cache:HIT(命中)/MISS(未命中),此处仅代表边缘节点的命中情况,不代表其父层节点的命中情况。 X-Swift-SaveTime:缓存在节点上保存的时间,零时区(北京时间+8H)。
CDN解析原理
域名就正式接入了CDN进行服务,那么此时终端用户访问时,DNS是如何工作的呢? 假设加速域名为 www.aliyundoc.com ,接入CDN开始加速服务后,当终端用户在北京发起HTTP请求时,处理流程如下图所示。
最后客户端在 HTTP 请求过程中可以通过检查 HTTP 响应的状态码和相关的响应头信息来判断是否命中了强缓存、CDN 缓存或协商缓存。以下是具体的判断方法:
1. 判断强缓存
强缓存是指客户端在本地缓存的资源,判断强缓存命中的条件主要依赖于以下响应头:
Cache-Control
:如max-age=3600
指示资源可以在缓存中保存 1 小时。Expires
:指定资源的过期时间。
判断方法:
- 当客户端请求资源时,如果发现本地缓存的资源的过期时间尚未到达,客户端直接使用本地缓存,而不会发送请求到服务器。
- 如果使用的是强缓存,客户端不会发送 HTTP 请求,因此没有响应头。
2. 判断 CDN 缓存
如果强缓存未命中,客户端会发送请求到 CDN 边缘服务器,这时 CDN 会根据其缓存策略进行响应。
判断方法:
状态码:
- 200 OK:表示 CDN 缓存命中,并从缓存中返回资源。
- 其他状态码(如 404、500 等):表示请求未成功,可能是资源不存在或服务器错误。
响应头:
X-Cache
(或类似头部):许多 CDN 会在响应中添加自定义头部来指示缓存状态,例如X-Cache: HIT
表示缓存命中,X-Cache: MISS
表示未命中。
3. 判断协商缓存
如果 CDN 没有缓存资源,或者强缓存已经过期,客户端可能会使用协商缓存。这种情况下,客户端会在请求中包含条件请求头:
If-Modified-Since
:包含上次缓存的时间。If-None-Match
:包含 ETag 值。
判断方法:
状态码:
- 304 Not Modified:表示资源未修改,客户端将继续使用本地缓存。
- 200 OK:表示资源已经更新,源站返回新的内容,并可能更新 CDN 缓存。
响应头:
- 如果响应中包含
Last-Modified
或ETag
,说明服务器支持协商缓存。
- 如果响应中包含
总结
客户端可以通过以下步骤判断缓存命中情况:
- 检查本地缓存:如果缓存有效,则直接使用强缓存。
- 发起请求到 CDN:如果强缓存未命中,观察 CDN 的响应状态。
- 200 OK 表示 CDN 缓存命中。
- 其他状态码 表示未命中。
- 协商缓存:如果请求包含
If-Modified-Since
或If-None-Match
,检查响应状态:- 304 Not Modified 表示使用本地缓存。
- 200 OK 表示资源更新并返回新内容。
通过这些机制,客户端能够有效地判断请求是否命中强缓存、CDN 缓存或协商缓存。
参考文章 :