http缓存

163 阅读5分钟

前言

web缓存可分为:浏览器缓存、服务器缓存、数据库缓存、CDN缓存。 而浏览器缓存又分为:http缓存、localStorage、sessionStorage、cookie等。 对于http缓存又分为强缓存和协商缓存。

使用http缓存的作用

  1. 减少网络带宽消耗。当http缓存副本被使用时,只会产生极小的网络流量,可以有效的降低运营成本
  2. 降低服务器压力,给网络资源设定有效期后,用户可以重复使用本地的缓存,减少对源服务器的请求,间接降低服务器的压力
  3. 减少网络延迟,加快页面打开速度,对于最终用户,缓存的使用能够明显加快页面打开速度,达到更好的体验

强缓存

对于强制缓存,服务器响应的header中会用两个字段来表明,expires和cache-control

  • expires:值为服务端返回的数据到期时间,当再次请求时的请求时间如果小于返回的此时间,则直接使用缓存数据。但由于服务端时间和客户端的时间可能有误差,这也将导致缓存命中的误差,并且,expires是http/1.0的产物,故现在大多数使用cache-control替代。

  • cache-control有很多属性,不同的属性代表的意义也不同。

    1. private:客户端可以缓存
    2. public:客户端和代理服务器都可以缓存
    3. max-age=t:缓存内容将在t秒后失效
    4. no-cache:实际的意思并不是不允许缓存,而是可以缓存,但在使用之前必须去服务器验证是否过期,是否有最新的版本
    5. no-store:所有内容都不会缓存,用于某些变化非常频繁的数据。例如秒杀页面
    6. must-revalidate:如果缓存不过期就可以继续使用,但过期了如果还想用就必须去服务器验证

    举例说明:去超市买西瓜。no-store:买来的西瓜不允许放进冰箱,要么立刻吃掉,要么立刻扔掉;no-cache:可以放进冰箱,但吃之前必须问问超市有没有更新鲜的,如果有,就去吃超市里的。(看来超市遇到大客户了);must-revalidate:可以放进冰箱,保鲜期内可以吃,过期了就要问问超市让不让吃(看来超市又遇到了个傻子);

    另外:Ctrl+F5的“强制刷新”它其实是发起了“cache-control: no-cache”,含义和“max-age=0”基本一样;

协商缓存

协商缓存需要对比判断是否可以使用缓存。浏览器第一次请求数据时,服务器会将缓存标识与数据一起响应给客户端,客户端将他们备份至缓存中。再次请求时,客户端会将缓存中的标识发送给服务器,服务器根据此标识来判断。若未失效,返回304状态码(not modified),浏览器拿到此状态码就可以直接使用缓存数据了。

last-modified / if-modified-since

last-modified:是一个响应首部字段,包含服务器认定的资源最后的修改时间。

if-modified-since:浏览器再次请求服务器的时候,请求头会包含此字段,后面跟着之前请求所获得的最后修改时间,该字段只能用在get或head请求中。服务端收到请求头发现有if-modified-since,则与被请求资源的最后修改时间进行对比,如果一致则返回304,此时客户端只需要从缓存中读取即可。

etag / if-none-match

etag:是一个响应首部字段,它是根据实体内容生成的一段hash字符串,标识资源的状态,由服务端产生。

if-none-match:是一个条件式的请求首部。如果请求资源时在请求头加上这个字段,值为之前服务端返回的资源上的etag,当且仅当服务器上没有任何资源的etag值能与此值匹配时,服务器才会返回带有所请求资源的实体的200响应。否则服务器会返回不带实体的304响应;etag优先级高于last-modified。

etag相较于last-modified的优势

  1. 某些情况下服务器无法获取资源的最后修改时间
  2. 资源的最后修改时间改变了,但是内容没有变,那么此时last-modified就不能有效的使用缓存
  3. 如果资源修改非常频繁,在秒以下的时间进行了修改,而last-modified只能精确到秒,那么此时服务器所做的处理可能会是有误的

强缓存与协商缓存的区别

强缓存命中的话不会发请求到服务器,协商请求一定会发请求到服务器,通过资源的请求首部字段验证资源是否命中协商缓存,如果协商缓存命中,服务器会将这个请求返回,但是不会返回这个资源的实体,而是通知客户端可以从缓存中加载这个资源(http状态码为304,not modified)。

浏览器不同刷新的区别

  1. 浏览器地址栏中输入url,回车,浏览器发现缓存中有这个文件了,不用继续请求了,直接去缓存拿(最快)
  2. F5刷新,告诉浏览器,别偷懒,好歹去服务器看看这个文件是否过期了。于是浏览器就胆胆襟襟的发送请求并带上if-modified-since
  3. Ctrl+F5刷新,告诉浏览器,你先把你缓存中的文件删了,然后再去服务器中请求个完整的资源下来,于是客户端完成了强制更新的操作。