前端缓存策略

2018-10-15  本文已影响77人  niklause_sun
cache.png

浏览器端的缓存规则

对于浏览器端的缓存来讲,这些规则是HTTP协议头HTML页面的Meta标签中定义的。他们分别从新鲜度校验值两个维度来规定浏览器是否可以直接使用缓存中的副本,还是需要去原服务器获取更新的版本。

新鲜度(过期机制):也就是缓存副本有效期。一个缓存副本必须满足一下几个条件,浏览器会认为它是有效的,足够新的:

满足以上两个情况的一种,浏览器会直接从缓存中获取副本并渲染。

校验值(验证机制):服务器返回资源的时候有时在控制头信息带上这个资源的实体标签Etag(Entity Tag),它可以用来作为浏览器再次请求过程的校验标识。如果发现校验标识不匹配,说明资源已经被修改或过期,浏览器需要重新获取资源内容。

缓存的作用

HTTP缓存机制

缓存行为主要由缓存策略决定,而缓存策略由内容拥有者设置。这些策略主要通过特定的HTTP头部来清晰的表达。

当一个用户发起一个静态资源请求的时候,浏览器会通过以下几个步骤来获取资源:

强制缓存

强制缓存就是想浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程,强制缓存的情况主要有三种,如下:

当浏览器想服务器发起请求时,服务器会将缓存规则放入HTTP响应报文的HTTP头中和请求结果一起返回给浏览器,控制强制缓存的字段分别是Expires和Cache-Control,其中Cache-Control优先级比Expires高。

Expires

Expires是HTTP/1.0控制网页缓存的字段,其值为服务器返回该请求结果缓存的到期时间,即在此发起该请求时,如果客户端的时间小于Expires的值时,直接使用缓存结果。

到了HTTP/1.1,Expire已经被Cache-Control替代,原因在于Expires控制缓存的原理是使用客户端的时间与服务端返回的时间做对比,那么如果客户端与服务端的时间因为某些原因(例如时区不同,客户端和服务端有一方的时间不准确)发生误差,那么强制缓存会直接失效,这样的话强制缓存的存在则毫无意义,那么Cache-Control又是如何控制的呢?

Cache-Control

在HTTP/1.1中,Cache-Control是最重要的规则,主要用于控制网页缓存,主要取值为:

cache-control: max-age=600
expires: Mon, 16 Apr 2018 01:41:50 GMT

由这个例子可以知道:

由于Cache-Control的优先级比expires高,那么直接根据Cache-Control的值进行缓存,意思就是说在600秒内再次发起该请求,则会直接使用缓存结果,强制缓存生效。

注:在无法确定客户端的时间是否与服务端的时间同步的情况下,Cache-Control相比于expires是更好的选择,所以同时存在时,只有Cache-Control生效。

缓存保存的位置

缓存有内存缓存和硬盘缓存两种

在浏览器中,浏览器会在js和图片等文件解析执行后直接存入内存缓存中,那么当刷新页面时只需直接从内存缓存中读取(from memory cache);而css文件则会存入硬盘文件中,所以每次渲染页面都需要从硬盘读取缓存(from disk cache)。

协商缓存

协商缓存就是强制缓存失效后,浏览器携带缓存标识想服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要有以下两种情况:

同样,协商缓存的标识也是在响应报文的HTTP头中和请求结果一起返回给浏览器的,控制协商缓存的字段有:Last-Modified/ If-Modified-Since和Etag / If-None-Match,其中Etag / If-None-Match的优先级比Last-Modified / If-Modified-Since高。

Last-Modified / If-Modified-Since

Last-Modified是服务器相应请求时,返回该资源文件在服务器最后被修改的时间,。

If-Modified-Since则是客户端再次发起该请求时,携带上次请求返回的Last-Modified值,通过此字段值告诉服务器该资源上次请求返回的最后被修改时间。服务器收到请求,发现请求头含有If-Modified-Since字段,则会根据If-Modified-Since的字段值与该资源在服务器的最后修改时间做对比,若服务器的资源最后被修改时间大于If-Modified-Since的字段值,则重新返回资源,状态码为200;否则则返回304,代表资源无更新,可继续使用文件。

Etag / If-None-Match

Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),如下。

If-None-Match是客户端再次发起该请求时,携带上次请求返回的唯一标识Etag值,通过此字段值告诉服务器该资源上次请求返回的唯一标识值。服务器收到该请求后,发现该请求头中含有If-None-Match,则会根据If-None_match的字段值与该资源在服务器的Etag值做对比,一致则返回304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为200。

tips:Etag / If-None-Match优先级高于Last-Modified / If-Modified-Since,同时存在则只有Etag / If-None-Match生效。

Etag/LastModified过程如下

  1. 客户端请求一个页面(A)。
  2. 服务器返回页面A,并在给A加上一个Last-Modified/Etag。
  3. 客户端展现该页面,并将页面连同Last-Modified/Etag一起缓存。
  4. 客户端再次请求页面A,并将上次请求时服务器返回的Last-Modified/Etag一起传递给服务器。
  5. 服务器检查该Last-Modified或Etag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304和一个空的响应体。

Etag主要为了解决Last-Modified无法解决的一些问题:

  1. 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
  2. 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的力度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);
  3. 某些服务器不能精确的得到文件的最后修改时间。

其他标签

Content-Length:尽管并没有在缓存中明确设计,Content-Length头部在设置缓存策略时很重要。某些软件如果不提前获知内容的大小以留出足够空间,则会拒绝缓存该内容。

Vary:缓存系统同行使用请求的主机和路径作为存储该资源的键。当判断一个请求是否是请求同样内容时,Vary头部被用来提醒缓存系统需要注意另一个附加头部。它通常被用来告诉缓存系统同样注意Accept-Encoding头部,以便缓存系统能够区分压缩和未压缩的内容。

服务器端的缓存

CDN缓存

CDN缓存,也叫网关缓存、反向代理缓存。浏览器先向CDN网关发起web请求,网关服务器后面对应着一台或多态负载均衡源服务器,会根据它们的负载请求,动态地请求转发到合适的源服务器上。

CND缓存策略

CDN边缘节点缓存策略因服务商不同而不同,但一般都会遵循http标准协议,通过http响应头中的Cache-control:max-age的字段来设置CDN边缘节点数据缓存时间。

当客户端向CDN节点请求数据时,CDN节点会判断缓存数据是否过期,若缓存数据并没有过期,则直接将缓存数据返回给客户端;否则,CDN节点就会向源站发出回源请求(back to the source request),从源站拉去最新数据,更新本地缓存,并将最新数据返回给客户端。

CDN服务商一般会提供基于文件后缀、目录多个维度来指定CDN缓存时间,为用户提供更精细化的缓存管理。

CDN缓存时间会对回源率产生直接的影响。若CDN缓存时间较多,CDN边缘节点上的数据会经常失效,导致频繁回源,增加了源站的负载,同时也增打了访问延时;若CDN缓存时间太长,会带来数据更新时间慢的问题。开发者需要增对特定的业务,来做特定的数据缓存时间管理。

CDN缓存刷新CDN边缘节点对开发者是透明的,相比于浏览器Ctrl+F5的强制刷新来使浏览器本地缓存失效,开发者可以通过CDN服务商提供的“刷新缓存”接口来达到清理CDN边缘节点缓存的目的。这样开发者在更新数据后,可以使用“刷新缓存”功能来强制CDN节点上的数据缓存过期,保证客户端在访问时,拉取到最新的数据。

CDN的优势

CDN缓存的缺点

当网站更新时,如果CDN节点上数据没有及时更新,即便用户在浏览器使用Ctrl+F5的方式使浏览器端的缓存失效,也会因为CDN边缘节点没有同步最新数据而导致用户访问异常。

Combo服务

Combo服务,也就是我们在最终拼接生成页面资源引用的时候,并不是生成多个独立的link标签,而是将资源地址拼接成一个url路径,请求一种线上的动态资源合并服务,从而实现减少HTTP请求的需求

/??file1,file2,file3,...的url请求响应就是动态combo服务提供的,它的原理很简单,就是根据url找到对应的多个文件,合并成一个文件来响应请求,并将其缓存,以加快访问速度。

但它也存在一些缺陷:

HTML5缓存思路

html5离线应用缓存manifest

manifest文件罗列了需要被缓存的文件清单。

CACHE MANIFEST
# wanz app v1

# 指明缓存入口
CACHE:
index.html
images/logo.png
scripts/main.js

# 以下资源必须在线访问
NETWORK:
login.php

# 如果index.php无法访问则用404.html代替
FALLBACK:
/index.php /404.html

这个过程中有几个问题需要注意:

LocalStorage

localStorage.fresh = "vfresh.org"; // 设置一个键值
var a = localStorage.fresh; // 获取键值

// API

// 清空storage
localStorage.clear();

//设置一个键值
localStorage.setItem("fresh", "vfresh.org");

// 获取一个键值
localStorage.getItem("fresh");

// return "vfresh.org" // 获取指定下表的键的名称(如同Array)
localStorage.key(0);

// return "fresh" // 删除一个键值
localStorage.removeItem("fresh");

与sessionStorage主要的区别是存储时间和作用域。

另外,严格来说localStorage更像cookie一类的本地数据存储。但是在标准缓存之外,开发人员可以用浏览器的一些功能来实现自定义的客户端“缓存”

构建可缓存站点的建议

引用

缓存策略-腾讯web前端

彻底理解浏览器的缓存机制

Cache缓存机制

上一篇 下一篇

猜你喜欢

热点阅读