喵空间

正文

# 浏览器缓存策略详解

作者:admin

浏览器缓存策略详解

响应头字段

如何缓存以及采取那种缓存策略,都要由服务器首先告诉浏览器。即在浏览器首次发出请求后,服务器发送给浏览器的响应头字段如下——

1. Cache-Contorl

Cache-Control,即缓存策略,是浏览器读取缓存策略第一站,这个字段告诉了浏览器我们应该采取那种缓存策略——

  1. private 仅允许客户端浏览器缓存
  2. public 代理服务器和客户端浏览器都可以缓存

特别的值,
3. max-age:时间(秒),指定浏览器本地缓存数据的时间。
max-age和private或public可以同时组合存在,例如

Cache-Control: max-age:3000,public
4. no-cache 不使用“本地计时缓存”,但不影响使用“协商缓存”

2. date

既然指定了缓存多久,那么,肯定要记录下当前请求的时间呀,这样才能开始缓存,并计算出什么时候到期嘛。

所以,服务器会在返回的响应中用date字段存下当前的时间提供给浏览器比对。实际上使用Cache-Control:max-age:xxx配合date是一个组合,告诉浏览器当前请求的时间,以及在本地应该缓存多久。这种由服务器告知,而后在本地缓存指定时间的缓存方式我们称之为“ 由本地计时决定的强制缓存 ”。

现在问个很关键的问题,如果本地计时已经超过了我们设置的时间,浏览器会重新请求服务器获得最新的资源吗?

3. Last-Modified

我们仔细观察服务器的响应,发现服务器还会提供一个Last-Modified字段,这个字段是做什么用的呢?

Last-Modified顾名思义,资源上一次编辑的时间,这里我们可以回答前面的提问,如果本地的缓存计时的时间到了,浏览器会重新请求服务器能够获取到最新的数据吗?

不不,虽然确实会重新请求服务器即再次发起请求,但是,浏览器会重新向服务器协商,询问接下来要怎么做。这个阶段我们称之为“ 由向服务器协商后决定的协商缓存 ”,又服务器决定浏览器是否能够拉取到最新数据。

浏览器在再次请求服务器的时候,会带上If-Modified-Since字段,也就是上次服务器提供的Last-Modified里面的时间,服务器收到这个字段以后,会在服务端对数据的实际编辑时间进行比对,检查数据是否有变动,如果有,返回最新的数据,用正常200响应;如果没有,不返回任何实际数据而只返回304-not modified状态码,告诉浏览器资源没有发生更改,继续使用本地的强缓存。同时服务器会提供新的Last-Modified时间,浏览器开始了新的一轮max-age配合Last-Modified缓存计时。

max-age不存在或者为0,则不需要计时,每次提供Last-Modified由服务器比对。实际上提供了max-age只是为了减少请求服务器比对的次数,节约服务器资源。

好了,到此为止浏览器基础的缓存策略的逻辑我们已经了解啦。下面上一张图,还有一些扩充知识。咦这张图里怎么多了一个Etag?

图片描述

实际上Etag是一种新的机制,可以取代Last-Modified,弥补L-m以时间为依据提供给服务器比对数据的一些不足。因为时间差如果很小就很难比对。

那么,类似于Last-Modified对应If-Modified-Sense。
Etag也对应了If-None-match

关于Etag的具体机制和用法可以自行搜索了解,本文不再介绍啦。

4. 总结

本地强缓存 配合 协商缓存的两种策略
策略一:max-age结合data配合last-modified(响应)和if-modified-sense(请求)
策略二:max-age结合data配合etag(响应)和if-none-match

如果cache-control没有提供max-age或者max-age为0,或者提供了no-cache
说明不采用本地强缓存,转而采用协商缓存。

此时将和服务器协商,依然是两种缓存策略:

仅使用协商缓存的两种策略
策略一:last-modified(响应)和if-modified-sense(请求)
策略二:etag(响应)和if-none-match

注意无论是哪一种方式,最终都要和服务器协商,即本地计时的强制缓存是可选的,而协商缓存是必然的。

回复

补充一些结论:

作者:admin

补充一些结论:

我现在的问题是,如果配置了max-age 10分钟,must-revalidate,同时又有etag。此时我有一张图片在10分钟以内(没过期),但是服务器的etag改了,那么这张图片会立即被刷新,还是等到10分钟以后被刷新

在HTTP缓存策略中,当同时配置了max-age和ETag时,即使资源在max-age指定的期限内(例如10分钟),只要服务器端资源的ETag发生了改变,客户端仍然会在下一次请求时发送If-None-Match头部与服务器进行验证。服务器会根据收到的If-None-Match头中的ETag值与当前资源的实际ETag进行比较:

如果服务器发现ETag匹配(即资源没有改变),则返回304 Not Modified状态码,指示客户端可以继续使用缓存的图片。
如果服务器发现ETag不匹配(即资源已经更新),则会返回200 OK状态码,并附带新的图片内容。
同时,如果响应头还包含了Cache-Control: must-revalidate指令,这意味着在缓存过期之前,浏览器必须在使用缓存前先向服务器验证资源是否仍然有效。因此,在这种情况下,一旦服务器的ETag发生变化,无论max-age设置的时间长短如何,客户端都会立即发起条件性请求来验证资源,并根据服务器响应的结果决定是否刷新图片内容。

所以must-revalidate不是控制在本地缓存失效后向服务器重新验证,而是使用本地缓存前就会先验证对吗?注意我说的先后顺序,之前验证和之后验证效果是不一样的

是的,您的理解是正确的。must-revalidate 指令确实是在客户端尝试使用本地缓存内容 之前 强制向服务器进行验证。

具体来说,当一个响应头部包含 Cache-Control: must-revalidate 时,这意味着在缓存内容到期(即过期或已达到 max-age)之后,以及在任何情况下(包括在缓存内容仍在有效期内),客户端在使用存储的缓存副本前必须先与原始服务器通信以确认资源是否仍然有效。

即使资源未过期(比如还在10分钟的max-age之内),如果同时存在ETag并且服务器端资源的ETag已经改变,客户端在发起请求时会携带 If-None-Match 请求头,并且服务器将基于这个请求头中的 ETag 进行对比。如果发现不匹配,则服务器会返回更新后的资源,而不是让客户端继续使用旧的缓存版本。

总之,must-revalidate 确保了无论何时,在使用缓存内容之前都会执行一次有效性检查。

查看回复
上一页
下一页
0%
站点地图友情链接:
喵宅苑
喵空间社区程序
络合兔
技术宅
莉可POI
Mithril.js
枫の主题社
Project1
午后少年
机智库
七濑胡桃
xiuno
幻想の博客