HTTP协议的缓存机制(Client端)
正在进行的项目正好涉及到了HTTP协议缓存的相关内容,在看了各种相关资料后,有了自己的理解。因此分享出来,一个是为了方便大家交流,也是能够加强自身记忆。毕竟,费曼学习法告诉我们,把学过的东西在讲个别人才是真正学懂了。
http协议缓存主要可以分为server side(服务端)和client side(客户端)缓存两种
- server side又可以分为三类:代理服务器缓存、方向代理服务器缓存(nginx反向代理缓存)和cdn;
- client side可以分为两类:HTTP协议缓存HTML标签缓存
其中html标签缓存是在html的meta标签中写入该页面的缓存需求。但是这种方式支持的浏览器较少,并不是主流的客户端缓存机制。
今天我们主要来研究一下客户端的 HTTP协议缓存。首先,先看一下浏览器发起一个请求的过程:
我们可以看到,在请求之前,浏览器会先判断本地缓存中是否有改请求的缓存,对于第一次请求,没有缓存,则向web服务器发送请求。同时,在接收到浏览器响应后,会对响应进行分析,按照响应策略,来进行缓存。
那么在浏览器进行第二次的请求之前会发生什么呢?别急,再此之前我们先介绍一下浏览器的缓存策略,方便对下面的理解。浏览器缓存策略分为如下:
- 缓存存储策略
缓存存储策略主要用来规定缓存的一些特征。包括是否可以被缓存,以及可以被那些浏览器缓存,缓存时间等 - 缓存过期策略
缓存过期策略主要用来表征缓存能够存储的时间。如果在正常时间内,缓存都是有效的 - 缓存对比策略
客户端将本地缓存与服务器中内容进行对比,确保本地缓存是有效的。这一点可以理解为,客户端并不是有了缓存就不向服务器请求了,而是会想客户端发送验证请求,当验证本地缓存无效了才会重新发送请求
下面我们继续看一下客户端的第二次请求
在第二次请求之前,还是会检测是否有缓存。如果检测到有缓存,会判断该缓存的有效性。先通过过期策略判断。如果没有指定其他的,而只有expiresTime,并且该事件没有过期,那么就证明缓存有效,不用去获取。如果expiresTime过期或者没有。则会进行对比策略。对比策略先进行E-tag对比。E-tag是服务端给资源自动生成的唯一标识符,对于文件更新之后,就会重新生成。服务器进行对比,如果发现不一样的话,就会重新发送资源,并请求头为200.如果一样,证明缓存有效,那么就发送304相应,让客户端从本地读取缓存。如果没有E-tag那么就使用last-modified策略。该策略会向服务器发送请求,然后服务器会对比改策略发来的修改时间同请求资源修改时间是否一致,如果不一样,本地缓存就作废。
虽然缓存策略分为三部分,但是其三部分是有相关联的。可以看下下面的图片
缓存存储策略主要通过Cache-Control来设置。其有一下几个参数:
- max-age
执行缓存被认为是最新的最长时间。类似于过期时间,这个参数是基于请求时间的相对时间间隔,而不是绝对过期时间,[秒]是一个数字,单位是秒:从请求时间开始到过期时间之间的秒数。 - s-maxage
类似于max-age属性,除了他应用于共享(如:代理服务器)缓存 - public
标记认证内容也可以被缓存,一般来说: 经过HTTP认证才能访问的内容,输出是自动不可以缓存的; - no-cache
强制每次请求直接发送给源服务器,而不经过本地缓存版本的校验。这对于需要确认认证应用很有用(可以和public结合使用),或者严格要求使用最新数据的应用(不惜牺牲使用缓存的所有好处); - no-store
强制缓存在任何情况下都不要保留任何副本 - must-revalidate
告诉缓存必须遵循所有你给予副本的新鲜度的,HTTP允许缓存在某些特定情况下返回过期数据,指定了这个属性,你高速缓存,你希望严格的遵循你的规则。 - proxy-revalidate
和 must-revalidate类似,除了他只对缓存代理服务器起作用
从上图也可以发现。cache-control不知规定了缓存的存储策略,其实也变相的规定了他的过期策略和对比策略。
要注意的是,如果cache-control的值被设置为no-cache并不是说不缓存了。而是说把他的缓存的max-age设定为0.也就是在每一次请求的时候,都认为该缓存是过期的,需要重新从服务器验证缓存的合法性。
最后,看一下请求头和响应头的对应关系
- .Last-Modified/If-Modified-Since
前者是响应头返回的资源最后修改时间,后者是请求头在请求改资源时候带着的资源信息。用来让服务器判断是否该资源是最新的 - ETag/If-None-Match
前者是响应头返回的资源在服务器中的唯一标识符,后者是用来在客服端再次请求该资源时候携带,让服务器来判断该资源是否和服务器上对应资源一致