1、前言作为一个前端,了解http缓存是非常必要,它不仅是面试的必要环节,也更是实战开发中必不可少需要了解的知识点,本文作者将从缓存的概念讲到如何在业务中设计一个合理的缓存架构,带你一步一步解开http缓存的神秘面纱。 2、http缓存定义当客户端向服务器请求资源时,会先抵达浏览器缓存,如果浏览器有“要请求资源”的副本,就可以直接从浏览器缓存中提取而不是从原始服务器中提取这个资源。http缓存一般针对GET请求,POST请求一般不会缓存,因为POST请求执行的任务都是对服务器产生副作用或者非幂等性的任务,既然要改变服务器资源,自然请求是要进入服务器进行处理的。缓存带来的好处是巨大的,减少了http请求,自然也就减少的服务端压力,并且增加了资源的访问速度,但是胡乱使用缓存,将会带来资源的不及时更新,甚至资源更新错位,灾难也是巨大的。 3、强缓存3.1、强缓存定义如果命中缓存,直接从缓存中拿数据,请求不会经过服务器,返回的http状态码为200(from disk cache) 下面给一张流程图来说明强缓存的请求过程,为了方便假设浏览器存在一个缓存数据库(其实就是disk磁盘,缓存数据存放的地方)。 仔细看上面的流程图,强缓存的最大特点就是在命中缓存的情况下不会经过服务器,而是直接返回。 3.2、Http头Expires/Cache-Control设置强缓存Cache-Control里面存在多个属性来控制缓存,设置强缓存即设置资源的有效期,属性为max-age. app.get('/script1.js', function (req, res, next) { // res.header('Cache-Control', 'must-revalidate, max-age=600') // res.header('Content-Type', 'text/html') res.header('Cache-Control', 'max-age=20') res.sendFile(__dirname + '/script.js')}) Expires和max-age都是用于控制缓存的生命周期。不同的是Expires指定的是过期的具体时间,例如Sun, 21 Mar 2027 08:52:14 GMT,而max-age指定的是生命时长秒数315360000。 4、协商/对比缓存4.1、定义协商缓存与强制缓存的不同之处在于,协商缓存每次读取数据时都需要跟服务器通信,并且会增加缓存标识。在第一次请求服务器时,服务器会返回资源,并且返回一个资源的缓存标识,一起存到浏览器的缓存数据库。当第二次请求资源时,浏览器会首先将缓存标识发送给服务器,服务器拿到标识后判断标识是否匹配,如果不匹配,表示资源有更新,服务器会将新数据和新的缓存标识一起返回到浏览器;如果缓存标识匹配,表示资源没有更新,并且返回 304 状态码,浏览器就读取本地缓存服务器中的数据。 再次访问: 还是给一张流程图来说明。(图是盗的,协商缓存也可以成为对比缓存,图中的对比缓存就是协商缓存) 4.2、协商缓存如何验证第一次请求将response header的Last-Modified和Etag存起来,在第二次请求通过request header的If-Modified-Since和If-None-Match传到服务端进行验证,如果命中缓存,返回304,不带返回的数据,浏览器自动从缓存中获取数据资源,若未命中缓存返回200,带上数据资源。 ** Last-Modified:** ** If-Modified-Since:** ** Etag / If-None-Match(优先级高于Last-Modified / If-Modified-Since) ** ** If-None-Match:** 4.3、Http头如何设置协商缓存在强缓存那一节说到使用Cache-Control的max-age来设置资源过期时间,那么当max-age=0的时候呢,自然浏览器第一时间发现资源过期,request header就会带着If-Modified-Since和If-None-Match去服务端验证。
就可以触发协商缓存了,其实Cache-Control中还有两个属性都可以设置协商缓存 must-revalidate和no-cache Cache-Control: must-revalidate, max-age=600 该头信息意义就是在资源有效期过后必须进行验证, 与只设置max-age=600的区别是,前面一个是MUST,而后面一个是SHOULD,理论上来说它们的效果是一致的。
如果要不缓存,每次都请求新的资源应该使用 Cache-Control: no-store 5、关于缓存的Http头总结5.1、'no-cache', 'no-store', 'must-revalidate'Cache-Control字段可以设置的不仅仅是max-age存储时间,还有其他额外的值可以填写,甚至可以组合。主要使用的值有如下: 5.2、Expires VS. max-ageExpires和max-age都是用于控制缓存的生命周期。不同的是Expires指定的是过期的具体时间,例如Sun, 21 Mar 2027 08:52:14 GMT,而max-age指定的是生命时长秒数315360000。 5.3、Etag VS. Last-ModifiedEtag和Last-Modified都可以用于对资源进行验证,而Last-Modified顾名思义,表示资源最后的更新时间。 5.4、max-age=0 VS. no-cachemax-age=0是在告诉浏览器,资源已经过期了,你应该(SHOULD)对资源进行重新验证了;而no-cache则是告诉浏览器在每一次使用缓存之前,你必须(MUST)对资源进行重新验证。 5.5、public VS. private要知道从服务器到浏览器之间并非只有浏览器能够对资源进行缓存,服务器的返回可能会经过一些中间(intermediate)服务器甚至甚至专业的中间缓存服务器,还有CDN。而有些请求返回是用户级别、是私人的,所以你可能不希望这些中间服务器缓存返回。此时你需要将Cache-Control设置为private以避免暴露。 6、缓存实战前面写了很多缓存的基础知识,那么如何设计一个可靠的缓存规则,这个其实得根据你的实际需求而定。
其他的资源可根据下面这张决策树来进行设置 7、memory cache“内存缓存”中主要包含的是当前文档中页面中已经抓取到的资源。例如页面上已经下载的样式、脚本、图片等。我们不排除页面可能会对这些资源再次发出请求,所以这些资源都暂存在内存中,当用户结束浏览网页并且关闭网页时,内存缓存的资源会被释放掉。 8、浏览器可能会限制Cache-Control头无效Linux公社的RSS地址:https://www./rssFeed.aspx 本文永久更新链接地址:https://www./Linux/2019-08/160265.htm |
|