🐱HTTP的缓存控制🐱

Android_Banner.jpg

我们客户端向服务器请求资源是一件成本较高的事情,因为链路较长、网络不可控;

我们需要把这个获取到的数据缓存起来啊,下次请求时尽可能使用缓存的数据;

HTTP本身是基于【请求-应答】模式,基于这个模式,缓存可分为【服务器缓存】和【客户端缓存】;

服务器的缓存控制(Cache-Control)

当我们需要一个资源时,是这样的:

  1. 浏览器先去拿本地缓存数据,没有缓存数据就发送请求,向服务器获取资源;

  2. 服务器就响应请求,返回资源,同时标记资源的有效期;

  3. 浏览器获取到资源并缓存,等待下次请求时优先使用;

示意图
HTTP缓存-Server缓存控制-Cache-Control.png
max-age

服务器中使用Cache-Control头字段来标记资源的有效期,值【max-age=30】代表这个资源只能缓存30秒,之后就过期不能使用了;

其中这个max-age所代表的时间起点时响应报文创建的时间也就是离开服务器的时刻,而不是客户端收到报文的时间,这点与Cookie中的Max-Age是有点区别的;

当我们max-age=6,其中传输过程花费4S,那么这个资源的有效期就剩2S了;

除了max-age的缓存控制字段,在头字段中还有其他三位老哥来精确【指示浏览器如何使用缓存】

no_store 不允许缓存

用于某些变化非常频繁的数据

no_cache 可以缓存

使用之前必须要去服务器验证是否过期,是否有最新的版本;

must_revalidate

如果缓存不过期就可以使用,如果过期就必须去服务器验证;

整体服务器缓存控制的流程图
HTTP缓存-服务器缓存控制流程图.png

客户端的缓存控制

在整个【请求-应答】模式中,对于Cache-Control字段控制缓存策略,不仅服务器可以发,浏览器也是可以发的;

刷新按钮的点击

当点击刷新按钮时,会在请求头中加入【Cache-Control: max-age=0】;

max-age=0表明我要一个最新的数据,服务器收到后也会返回一个新的报文;

Ctrl+F5强制刷新

请求报文头字段中【If-Modified-Since】和【If-None-Match】会被清空返回最新数据;

浏览器中的缓存什么时候生效?

上述我们说的两种情况,都没有使用浏览器缓存,都是向服务器要最新的数据,那么什么时候使用自己的缓存呢?

结论

浏览器中的【前进】和【后退】

条件请求

当浏览器中使用【Cache-Control】做缓存控制都是向服务器请求最新数据刷数据,不能充分体现出缓存数据的作用;并且缓存数据还会失效,使用前还必须去服务器验证是否失效;

两个连续的请求组成的【验证动作】
  • 先发送一个HEAD请求,获取当前资源修改的时间等元信息,与缓存数据进行对比,没有变化就使用缓存,否则就发送请求获取最新的数据;

  • 两次请求的网络成本比较高,HTTP协议定义了一系列【If】开头的【条件请求】字段,专门用来验证资源是否过期,把上述两步做的事情合并成一步;

If开头的条件请求字段

条件请求中共有5个头字段

【If-Modified-Since】和【If-None-Match】是最常用的两个

我们需要在第一次的响应报文中预先携带【Last-modified】和【ETag】,然后第二次请求时需要带上缓存里的原值就可以;


HTTP缓存控制-IF条件控制.png

当缓存没有过期,服务器就返回一个【304 Not Modified】表示缓存依然有效,可以正常使用缓存;

Last-modified

表示资源最后修改的时间

ETag

实体标签(Entity Tag)的缩写,是资源的一个唯一标识;

主要用来解决修改时间无法准确区分文件变化的问题;

比如一个文件在1秒内修改了多次,因为修改时间是秒级的,这一秒内新版本无法区分;

比如一个文件会定期更新,但有时候会有同样的内容,但是时间在不断的变化,这是就会错误认为文件发生改变,就讲资源传输给浏览器,这样就浪费了带宽;

ETag的【强】【弱】之分

【强】ETag要求资源在字节级别上完全相同

【弱】ETag在值前有两个【W/】标记,仅仅要求资源在语义上没有变化,内部可能会有部分发生变化

比如HTML里的标签顺序的调整,或者多了几个空格;

上述我们的缓存Cache是缓存整个报文,不要错认为是body了哟!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。