文章目录
前言
浏览器缓存是前后端以及CDN的常用技术,可以减少对服务端的请求压力,减少客户端网络流量,并加快浏览器页面的加载。
一、浏览器缓存是什么?
浏览器缓存,是指浏览器本地缓存了已请求成功过的服务器文件,在下次加载文件时,根据缓存策略从浏览器本地缓存中读取或者从服务器读取。
例如,disk cache就是典型的浏览器缓存。
浏览器缓存的发起方是服务器(包括应用服务器、CDN、Nginx代理服务器等)。服务器在某次HTTP的response中设置header参数,表示启用浏览器缓存,浏览器收到后,遵循HTTP的规范,在下一次request中触发浏览器缓存。
HTTP有2种浏览器缓存策略:强缓存策略和协商缓存策略。
二、强缓存策略
强缓存策略,是指在缓存文件有效期内,直接加载缓存文件,不再向服务器发起请求。
强缓存策略有2种设置方式:Expires和Cache-Control(Http1.0中还有Pragma,等同于Cache-Control no cache)。
1. Expires
服务器在response头中设置Expires过期时间,如图所示。
Expires是http1.0版本的产物,使用的是服务器时间,精确到秒,因此有客户端时间不一致的问题。在http1.1中被Cache-Control替代。
2. Cache-Control
服务器在response头中设置Cache-Control(request头中也可以设置),如图所示。
常见的Cache-Control字段:
public 指明响应可以被任何缓存保存。
private 表明响应消息的部分或所有部分是为一个用户准备的并且不得被共享缓存保存。
no-cache 缓存不能利用此响应在没有通过源服务器对它进行成功的重验证的情况下去满足后续的请求。
no-store 如果在请求里被发送,一个缓存不能保存此请求或此请求响应的任何部分。如果在响应里被发送,一个缓存不能保存此响应或引起此响应请求的任何部分。
max-age=XX 表明客户端愿接受一个这样一个响应,此响应的年龄不大于客户端请求里max-age指定时间(以秒为单位)。
请参照:rfc2616中的14.9
三、协商缓存策略
协商缓存策略,是指浏览器向服务器发送请求,并带上缓存参数,由服务器来判定是否过期并做相应的返回。
协商缓存策略有2种设置方式:Last-Modified和Etag。
1. Last-Modified
服务器在response头中设置Last-Modified;浏览器在下次请求的头中设置If-Modified-Since,如图所示。
Last-Modified精确到秒,代表了服务器中文件的最后修改时间。
If-Modified-Since值等于上次获得的Last-Modified,代表了浏览器端缓存文件的最后修改时间。
服务器收到请求后,对比文件最新修改时间和请求中的If-Modified-Since,如果未变则返回304,变更则返回200和最新文件。
2. Etag
服务器在response头中设置Etag;浏览器在下次请求的头中设置If-None-Match,如图所示。
Etag是文件指纹,需要服务器消耗CPU资源计算得到。
If-None-Match值等于上次获得的Etag,代表了浏览器端缓存文件的指纹。
服务器收到请求后,计算最新文件的Etag,对比请求中的If-None-Match,如果未变则返回304,变更则返回200和最新文件。
Etag解决的第一个问题是,文件未变,但是服务器记录的文件时间变了(例如:CDN拉取源站后缓存),此时Last-Modified会认为文件变了而返回文件;
Etag解决的另一个问题是,Last-Modified只精确到秒,同一秒内文件被反复修改,无法正确反映出来。
四. 缓存策略执行顺序
1. 同策略优先级
允许同策略的缓存字段同时设置,同策略优先级如下:
强缓存:
Cache-Control > Expires,即2者并存时先判断Cache-Control。
协商缓存:
Etag > Last-Modified,即2者并存时先判断Etag。
2. 不同策略执行顺序
允许不同策略的缓存字段同时设置,浏览器先执行强缓存,已过期再执行协商缓存,具体如下:
- 第一次请求时,服务器返回200,并在respone headers中设置缓存参数。
- 第二次请求时,如图所示,浏览器判断缓存参数,命中强缓存就直接200,不再请求服务器;否则开始协商缓存,向服务器发起请求,若文件未改变则返回304(Not Modified),否则服务器会返回新的文件。
3. 只启用协商缓存策略
如果没有开启强缓存,只开启了协商缓存,浏览器会根据 Last-Modified自行推算缓存时长。也就是说,只有协商缓存情况下,浏览器也不一定会立刻向服务器发起请求,它会根据推算的缓存时长直接读取本地缓存,返回200,如图所示。
缓存时长的算法,不同浏览器各自实现,Chrome并没有公布,Firefox的算法是:缓存时长 = (Date - Last-Modified) / 10,即如果文件已经很久没变了,那么认为它以后变的可能性也不高,推算的缓存时长较大。
五. CDN
1. CDN加速原理
内容分发网络CDN(Content Delivery Network),将源站资源缓存到CDN节点,当终端用户请求访问和获取源站资源时无需回源,可就近获取CDN节点上已经缓存的资源,提高资源访问速度,同时分担源站压力。
CDN加速后,有可能会触发浏览器协商缓存,如图所示:
下面的例子来自阿里云,注意,CNAME是CDN替换域名的关键。
假设加速域名为www.aliyundoc.com,接入CDN开始加速服务后,当终端用户在北京发起HTTP请求时,处理流程如下图所示。
1.当终端用户向www.aliyundoc.com下的指定资源发起请求时,首先向Local DNS(本地DNS)发起请求域名www.aliyundoc.com对应的IP。
2.Local DNS检查缓存中是否有www.aliyundoc.com的IP地址记录。如果有,则直接返回给终端用户;如果没有,则向网站授权DNS请求域名www.aliyundoc.com的解析记录。
3.当网站授权DNS解析www.aliyundoc.com后,返回域名的CNAME www.aliyundoc.com.example.com。
4.Local DNS向阿里云CDN的DNS调度系统请求域名www.aliyundoc.com.example.com的解析记录,阿里云CDN的DNS调度系统将为其分配最佳节点IP地址。
5.Local DNS获取阿里云CDN的DNS调度系统返回的最佳节点IP地址。
6.Local DNS将最佳节点IP地址返回给用户,用户获取到最佳节点IP地址。
7.用户向最佳节点IP地址发起对该资源的访问请求。
8.如果该最佳节点已缓存该资源,则会将请求的资源直接返回给用户(步骤8),此时请求结束。
如果该最佳节点未缓存该资源或者缓存的资源已经失效,则节点将会向源站发起对该资源的请求。获取源站资源后结合用户自定义配置的缓存策略,将资源缓存到CDN节点并返回给用户(步骤8),此时请求结束。
2. CDN的浏览器缓存
CDN缓存了源站上的文件,因此,CDN存在文件过期的问题,用户访问CDN时,可能会得到过期的文件。CDN存在2种过期:
(一)CDN缓存文件的过期
如果源站文件的访问服务没有提供协商缓存参数,那么CDN只能根据后台配置的缓存策略,对缓存文件进行过期判定。因此,CDN会返回Etag和Last-Modified,它表达的是CDN缓存的过期,而不是源站文件的过期。
(二)源站文件的过期
如果源站文件的访问服务有提供协商缓存参数,那么CDN可以根据缓存参数动态调整过期判定,具体根据CDN实现和缓存配置而定。此时,CDN有可能返回源站文件的Etag和Last-Modified。
总结
本文简单介绍了浏览器缓存,再结合CDN进一步介绍了浏览器缓存的情况。