前言
缓存一直是一个前端的痛点,相信很多前端在面试的时候,大多是都遇到过缓存问题。接下来我们一起来学习
优点
相信大家都知道缓存的好处,那这里还是再简单的唠叨一下~~
缓存是用来提高性能的一项必不可少的技术 ,利用这项技术可以很好地提高web的性能:
1.打开本地资源速度当然比请求回来再打开要快得多。
2.缓存可以很有效地降低网络的时延,同时也会减少大量请求对于服务器的压力。
3.缓存可以减少带宽消耗。
一个小的概念
首先我们要知道——缓存实际上就是——请求资源的拷贝。
思考一个小问题——如果每次请求都将资源保存下来,那岂不是很傻逼的做法吗?内存被大量的消耗,开发者不易维护,没有固定的协议告诉我,这个缓存什么时候过期,什么时候需要请求新的资源,之前的缓存的资源在本次请求中是否还有用,自然的,客户端也会崩溃。
如何解决——那就是利用HTTP协议,HTTP协议是我们每次请求必经之路,那么通过HTTP协议来确定上面的这些问题在合适不过了。
缓存分类
第一种分类:
1. 共享缓存:各级代理缓存的资源。
2. 私有缓存:用户专有的资源。
第二种分类(后端---->前端):
1. 数据库缓存:
对于系统一些非常复杂的查询,可以将查询到的结果保存在内存中,下次就不需要查询数据库,导致数据库鸭梨三大,而是直接从内存中读取即可。
2. 网关缓存:
也被称为“反向代理缓存”或“替代缓存”。网关缓存起中介作用,多半是网站管理员(公司专门的运维工程师、或UED或程序组某人Add)部署,这样更容易扩展与维护。可以有多种方法把请求路由到网关缓存,但通常使用某种形式的负载均衡器,使它们看起来像源服务器。[此处不深入展开]
3. 代理服务器缓存:
也被称为“正向代理缓存”,代理服务器缓存原理为成千上万的用户提供缓存机制。每一次请求先发送到代理服务器上,代理服务器存在请求的数据,则返回给客户端,不存在就转发到源服务器并取得响应结果后,再返回给客户端。同一个缓存可能会被重用多次,减少响应时间和带宽以及源服务器的鸭梨。
4. 浏览器缓存:
相信你开发某个网站时,肯定使用过“清空缓存”来解决问题,这就是在清除缓存在本地磁盘上的资源数据。在本地缓存是非常有用的,访问本地与发送请求接受请求,快了不知多少倍呢。
对于上面几种缓存,前端遇到最多的就是浏览器缓存了吧,接下来我们一起来深入理解浏览器缓存吧~
浏览器缓存
对于一个完整的HTTP GET请求缓存过程会包含几个主要的步骤:
①客户端读取请求报文并且对报文进行解析, 提取URL和各种首部。
②查询是否在本地有请求资源副本,如果本地没有资源副本就会从服务器上获取资源,并且保存在本地。
或者:接着会进行查看资源副本是否足够新鲜(新鲜度检测), 如果缓存已经失效就会询问服务器是否有任何更新。
③服务器用新的首部和已缓存的主体来构建一条响应报文。
④服务器将响应报文发送给客户端。
⑤客户端读取响应报文进行相应的操作。
先来看一张浏览器缓存过程的的图片,可以不看具体内容,接下来我们会根据本图详细讲解浏览器缓存~
划重点:根据缓存处理方式的不同,接着浏览器缓存又分为又会分为:强缓存阶段、协商缓存阶段 、启发式缓存阶段。一起来看看吧~~
强缓存
在阅读下面知识点,请自行解决请求头和报文头,三次握手等相关的网络知识点。好了,接下来我们正式开始理解~~
强缓存主要是响应头中的Cache-Control和Expires两个字段进行控制的。
Expires:HTTP/1.0中定义,指定了一个绝对的过期时期,但设计之初存在着缺陷:如果本地时间和服务器时间相差太大,就会导致缓存错乱。
Cache-Control:HTTP 1.1中定义,Cache-Control:max-age定义了一个最大使用期,就是从第一次生成文档到缓存不再生效的合法生存时间。
同时使用:当然是HTTP协议高的优先级高,不然要再来一个缓存字段干嘛?所以 Cache-Control > Expires。
一个场景:当浏览器再次访问之前访问过的CSS文件时,发现本地这个文件的缓存,就根据上一次的响应头判断是否过期,没过期,使用缓存加载文件。但是过期了呢???请接着看~~
过期之后,ETag 和 Last-Modified 就开始参与强缓存的判断了。
Last-Modified:文件最后一次修改的时间。
ETag:对文件的一个标记。可能是抗碰撞散列函数、最近修改时间戳的哈希值、甚至只是一个版本号等等。
协商缓存
强缓存机制如果检测到缓存失效,就需要进行服务器再验证,这种缓存机制也称作协商缓存。
1. 当浏览器再次试图访问CSS文件,发现缓存过期,如果上一次的响应头中有ETag 和 Last-Modified,就会在本次请求的请求头里携带If-Moified-Since和If-None-Match这两个字段,进入步骤2。如果上一次的响应头中没有ETag 和 Last-Modified,就直接像服务器发送请求,进入步骤4。
2. 服务器通过If-Moified-Since和If-None-Match这两个字段来判断资源是否有修改,如果有修改则返回状态码200和新的内容,如果没有修改返回状态码304。
3. 浏览器收到200状态码,相当于首次访问这个文件,该怎么处理就怎么处理。浏览器收到304状态码,知道本地缓存虽然过期但仍然可以用,加载本地缓存。
4. 根据新返回的响应头来设置缓存。
启发式缓存
浏览器用来确定缓存过期时间的字段一个都没有时,那该怎么办?浏览器进入启发式缓存阶段。
根据响应头中2个时间字段 Date 和 Last-Modified 之间的时间差值,取其值的10%作为缓存时间周期。
这个阶段很容让人忽视,但实际上每时每刻都在发挥着作用。所以在今后开发过程中如果遇到默认缓存的坑,要知道浏览器只是在遵循启发式缓存协议而已。
附加知识点
关于缓存是从磁盘中获取还是从内存中获取,Chrome会根据本地内存的使用率来决定缓存存放在哪,如果内存使用率很高,放在磁盘里面,内存的使用率很高会暂时放在内存里面。这就可以比较合理的解释了为什么同一个资源有时是from memory cache有时是from disk cache的问题了。
完结
再去看看上边的图吧,很好的解释了浏览器缓存过程~~
参考文章:前端性能优化之缓存之路、缓存详解