一、简介
http协议缓存分为强制缓存和协商(对比)缓存。
区别:
1、强缓存命中的话不会发请求到服务器
2、协商缓存一定会发请求到服务器,通过资源的请求首部字段验证资源是否命中协商缓存,如果协商缓存命中,服务器会将这个请求返回,但是不会返回这个资源的实体,而是通知客户端可以从缓存中加载这个资源。
两类缓存规则可以同时存在,强制缓存优先级高于对比缓存,也就是说,当执行强制缓存的规则时,如果缓存生效,直接使用缓存,不再执行对比缓存规则。
二、强制缓存
强制缓存,在缓存数据未失效的情况下,可以直接使用缓存数据。
在首次向服务器发送请求时,服务器会将数据和缓存规则一并返回,缓存规则信息包含在响应header中。
对于强制缓存来说,响应header中会有两个字段来标明失效规则(Expires/Cache-Control)。
1、 Expires
Expires是HTTP1.0标准中的字段,是一个绝对的时间点。
为服务端返回的到期时间,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。
缺点就是到期时间是由服务端生成的,但是客户端时间可能跟服务端时间有误差,这就会导致缓存命中的误差。
现在默认浏览器均默认使用HTTP 1.1,所以它的作用基本忽略。在HTTP 1.1版开始,使用Cache-Control替代
2、Cache-Control
Cache-Control中设定的时间会覆盖Expires中指定的时间
Cache-Control 是最重要的规则。常见的取值有private、public、no-cache、max-age,no-store,默认为private。
private:
客户端可以缓存
public:
客户端和代理服务器都可缓存(前端,可以认为public和private是一样的)
max-age=xxx:
缓存的内容将在 xxx 秒后失效
no-cache:
设置no-cache相当于max-age=0即数据缓存在本地但立即失效,需要使用对比缓存来验证缓存数据的有效性。
no-store:
所有内容都不会缓存,强制缓存,对比缓存都不会触发
三、协商(对比)缓存
对比缓存,顾名思义,需要进行比较判断是否可以使用缓存。
浏览器第一次请求数据时,服务器会将缓存标识与数据一起返回给客户端,客户端将二者备份至缓存数据库中。再次请求数据时,客户端将备份的缓存标识发送给服务器,服务器根据缓存标识进行判断,判断成功后,返回304状态码,通知客户端比较成功,可以使用缓存数据。
对比缓存缓存标识一共分为两种标识传递:Last-Modified/If-Modified-Since和Etag/If-None-Match(优先级高于Last-Modified/If-Modified-Since)
1、Last-Modified/If-Modified-Since
Last-Modified:
服务器在响应请求时,告诉客户端资源的最后修改时间。
If-Modified-Since:
再次请求服务器时,客户端通过此字段通知服务器上次请求时,服务器返回的资源最后修改时间。服务器收到请求后发现有头If-Modified-Since 则与被请求资源的最后修改时间进行比对。若资源的最后修改时间大于If-Modified-Since,说明资源又被改动过,则响应整片资源内容,返回状态码200;若资源的最后修改时间小于或等于If-Modified-Since,说明资源无新修改,则响应HTTP 304,告知浏览器继续使用所保存的cache。
2、Etag/If-None-Match(优先级高于Last-Modified/If-Modified-Since)
Etag:
服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器决定)。
If-None-Match:
再次请求服务器时,通过此字段通知服务器客户段缓存数据的唯一标识。服务器收到请求后发现有头If-None-Match 则与被请求资源的唯一标识进行比对。不同,说明资源又被改动过,则响应整片资源内容,返回状态码200;相同,说明资源无新修改,则响应HTTP 304,告知浏览器继续使用所保存的cache。
3、Last-Modified比较难解决的问题:
<1> Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间.
<2> 如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存
<3> 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形。
Etag在HTTP1.1中提出。主要为了解决Last-Modified无法解决的一些问题。Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。