HTTP Cache 浅析

本文转载至jquery

深刻理解浏览器的缓存机制算法

HTTP Cache 为何让人很困惑浏览器

查看栗子:缓存

基于http协议讲解缓存头Cache-Control在服务中的应用bash

1、Private browser caches 和 Shared proxy caches

缓冲这块并不怎么好理解,网上查阅的资料,都讲的比较模糊,就好比:Private browser cachesShared proxy caches服务器

浏览器缓存的服务架构多是这样的:浏览器(Cache)<=>服务器。
代理服务器缓存架构多是这样的:浏览器 <=> CDN(Cache)<=>源服务器。
复制代码

不一样的 HTTP Cache 解决的问题和使用的场景是不同的。我的理解浏览器缓存主要是为了不没必要要的请求和大量的网络传输,而代理服务器缓存主要是为了让服务离用户更近更有效率(固然也解决了请求和网络传输)。网络

对于 Web 开发者来讲,可能常常遇到的仍是浏览器缓存,当咱们访问一个网站的时候,会进行缓冲,当咱们下一次访问的时候,可能看到的就是缓冲中加载的页面。这样能够大大加快访问速度。架构

2、正确理解 Cache-Control 指令

这个指令是一个通用首部字段,就是说这个指令可以做为请求和响应指令,同时这个指令的参数也有多个,好比说其参数 max-age = 0 在请求和响应指令中分别表明什么?在理解的时候必定要分辨清楚。负载均衡

3、进一步理解 Cache-Control 指令

它有三个含义:性能

(1)可否缓存(针对响应来讲)

private:表示它只应该存在与浏览器缓存。
public:表示它能够缓存在浏览器或者 CDN 上。
no-cache:这个词很迷惑,不是表明不能使用缓存,而是表明在使用前必须到服务器上确认。
no-store:表示不容许被缓存。
复制代码

(2)缓存多久(针对响应来讲)

max-age= 秒,告知浏览器这个缓存的有效时间多少。
复制代码

(3)revalidation(针对响应来讲,就是条件检查)

must-revalidate:
表示浏览器必须检查服务器,确认本地缓存是否有效,这个参数和请求参数 max-age = 0 有些相似。
复制代码

这个指令形象的告诉浏览器,你是否是能够缓存这个对象,这个对象缓存时间是多少,是否在每次使用缓存的时候先确认下。

一张图描述的很清晰:

  • 这个资源是否容许缓存?
  • 客户端每次使用缓存的时候须要去服务器校验吗?
  • 这个缓存是 Public 的仍是 Private?
  • 缓存时间多少?
  • 资源标识符是什么(Etag)?

4、Expires和Cache-Control二者对比

其实这二者差异不大,区别就在于 Expires 是http1.0的产物,Cache-Control是http1.1的产物,二者同时存在的话,Cache-Control优先级高于Expires;在某些不支持HTTP1.1的环境下,Expires就会发挥用处。因此Expires实际上是过期的产物,现阶段它的存在只是一种兼容性的写法。

5、协商缓冲

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

  • 协商缓存生效,返回304和Not Modified

  • 协商缓存生效 ,返回200和请求结果

协商缓存能够经过设置两种 HTTP Header 实现:Last-Modified 和 ETag 。

1.Last-Modified和If-Modified-Since

浏览器在第一次访问资源时,服务器返回资源的同时,在response header中添加 Last-Modified的header,值是这个资源在服务器上的最后修改时间,浏览器接收后缓存文件和header

Last-Modified: Fri, 22 Jul 2016 01:47:00 GMT
复制代码

浏览器下一次请求这个资源,浏览器检测到有 Last-Modified这个header,因而添加If-Modified-Since这个header,值就是Last-Modified中的值;服务器再次收到这个资源请求,会根据 If-Modified-Since 中的值与服务器中这个资源的最后修改时间对比,若是没有变化,返回304和空的响应体,直接从缓存读取,若是If-Modified-Since的时间小于服务器中这个资源的最后修改时间,说明文件有更新,因而返回新的资源文件和200

可是 Last-Modified 存在一些弊端:

若是本地打开缓存文件,即便没有对文件进行修改,但仍是会形成 Last-Modified 被修改,服务端不能命中缓存致使发送相同的资源 由于 Last-Modified 只能以秒计时,若是在不可感知的时间内修改完成文件,那么服务端会认为资源仍是命中了,不会返回正确的资源

既然根据文件修改时间来决定是否缓存尚有不足,可否能够直接根据文件内容是否修改来决定缓存策略?因此在 HTTP / 1.1 出现了 ETagIf-None-Match

2.ETag和If-None-Match

Etag是服务器响应请求时,返回当前资源文件的一个惟一标识(由服务器生成),只要资源有变化,Etag就会从新生成。浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到request header里的If-None-Match里,服务器只须要比较客户端传来的If-None-Match跟本身服务器上该资源的ETag是否一致,就能很好地判断资源相对客户端而言是否被修改过了。若是服务器发现ETag匹配不上,那么直接以常规GET 200回包形式将新的资源(固然也包括了新的ETag)发给客户端;若是ETag是一致的,则直接返回304知会客户端直接使用本地缓存便可。

3.二者之间对比:

  • 首先在精确度上,Etag要优于Last-Modified。

Last-Modified的时间单位是秒,若是某个文件在1秒内改变了屡次,那么他们的Last-Modified其实并无体现出来修改,可是Etag每次都会改变确保了精度;若是是负载均衡的服务器,各个服务器生成的Last-Modified也有可能不一致。

  • 第二在性能上,Etag要逊于Last-Modified,毕竟Last-Modified只须要记录时间,而Etag须要服务器经过算法来计算出一个hash值。
  • 第三在优先级上,服务器校验优先考虑Etag

6、缓存机制

一般浏览器缓存策略分为两种:强缓存和协商缓存。若是缓存过时了,咱们就可使用协商缓存来解决问题。协商缓存须要请求,若是缓存有效会返回 304。

7、实际场景应用缓存策略

频繁变更的资源

Cache-Control: no-cache
复制代码

对于频繁变更的资源,首先须要使用Cache-Control: no-cache 使浏览器每次都请求服务器,而后配合 ETag 或者 Last-Modified 来验证资源是否有效。这样的作法虽然不能节省请求数量,可是能显著减小响应数据大小。

不常变化的资源

Cache-Control: max-age=31536000
复制代码

一般在处理这类资源时,给它们的 Cache-Control 配置一个很大的max-age=31536000 (一年),这样浏览器以后请求相同的 URL 会命中强制缓存。

而为了解决更新的问题,就须要在文件名(或者路径)中添加hash, 版本号等动态字符,以后更改动态字符,从而达到更改引用 URL 的目的,让以前的强制缓存失效 (其实并未当即失效,只是再也不使用了而已)。 在线提供的类库 (如 jquery-3.3.1.min.js, lodash.min.js 等) 均采用这个模式。

8、用户行为对浏览器缓存的影响

所谓用户行为对浏览器缓存的影响,指的就是用户在浏览器如何操做时,会触发怎样的缓存策略。主要有 3 种:

  • 打开网页,地址栏输入地址: 查找 disk cache 中是否有匹配。若有则使用;如没有则发送网络请求。

  • 普通刷新 (F5):由于 TAB 并无关闭,所以 memory cache 是可用的,会被优先使用(若是匹配的话)。其次才是 disk cache。

  • 强制刷新 (Ctrl + F5):浏览器不使用缓存,所以发送的请求头部均带有 Cache-control: no-cache(为了兼容,还带了 Pragma: no-cache),服务器直接返回 200 和最新内容。

相关文章
相关标签/搜索