-
2021-03-05 23:40:45
HTTP缓存类型
200 from cache:直接从本地缓存获取响应,可细分为from disk cache, from memory cache
304 Not Modified:协商缓存,本地未命中发送校验数据到服务端,如果服务端数据没有改变,则读取本地缓存响应
200 OK:不读取缓存,服务器返回完整响应
本地缓存相关Header(Response)
Pragma(1.0):设置为no-cache时会禁用本地缓存
Expires(1.0):值为格林威治时间,在这个时间前缓存有效无需发送请求
Cache-Control:缓存过期时间间隔
no-store:禁止缓存响应
no-cache:先发起请求和服务器协商,通过才能缓存响应
max-age=delta-seconds:告知浏览器该响应本地缓存有效的最长期限,以秒为单位
优先级:Pragma > Cache-control > Expires
协商缓存相关Header(Response)
Last-Modified:最后修改时间, If-Modified-Since(Request),发送到服务器的验证时间
ETag:文件的指纹标识符,随着文件内容改变而改变,If-None-Match(Request),发送到服务器的验证标识符
适合缓存的内容
直接缓存:js,css,图片,媒体文件
协商缓存:HTML,经常改变的js,css,图片,媒体文件
不适合缓存
用户隐私数据
经常改变的api接口数据
拒绝缓存:使用签名,如.js?签名
Nginx
add_header
本地缓存配置
expire:通知浏览器过期时长, expire time;
负值:cache-control:no-cache
正值:cache-control:max-age=指定时间
max:cache-control:max-age=10年后
协商缓存配置
Etag on|off,默认是on
更多相关内容 -
浏览器缓存机制
2021-03-14 17:27:11常用的缓存Memory CacheMemory Cache 也就是内存中的缓存,主要包含的是当前中页面中已经抓取到的资源,例如页面上已经下载的样式、脚本、图片等。读取内存中的数据肯定比磁盘快,内存缓存虽然读取高效,可是缓存持续...常用的缓存
Memory Cache
Memory Cache 也就是内存中的缓存,主要包含的是当前中页面中已经抓取到的资源,例如页面上已经下载的样式、脚本、图片等。读取内存中的数据肯定比磁盘快,内存缓存虽然读取高效,可是缓存持续性很短,会随着进程的释放而释放。 一旦我们关闭 Tab 页面,内存中的缓存也就被释放了。
那么既然内存缓存这么高效,我们是不是能让数据都存放在内存中呢?
这是不可能的。计算机中的内存一定比硬盘容量小得多,操作系统需要精打细算内存的使用,所以能让我们使用的内存必然不多。
需要注意的事情是,内存缓存在缓存资源时并不关心返回资源的HTTP缓存头Cache-Control是什么值,同时资源的匹配也并非仅仅是对URL做匹配,还可能会对Content-Type,CORS等其他特征做校验。
Disk Cache
Disk Cache 也就是存储在硬盘中的缓存,读取速度慢点,但是什么都能存储到磁盘中,比之 Memory Cache 胜在容量和存储时效性上。
在所有浏览器缓存中,Disk Cache 覆盖面基本是最大的。它会根据 HTTP Herder 中的字段判断哪些资源需要缓存,哪些资源可以不请求直接使用,哪些资源已经过期需要重新请求。并且即使在跨站点的情况下,相同地址的资源一旦被硬盘缓存下来,就不会再次去请求数据。绝大部分的缓存都来自 Disk Cache
浏览器会把哪些文件丢进内存中?哪些丢进硬盘中?
关于这点,网上说法不一,不过以下观点比较靠得住:
对于大文件来说,大概率是不存储在内存中的,反之优先
当前系统内存使用率高的话,文件优先存储进硬盘
强缓存
强缓存:不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的Network选项中可以看到该请求返回200的状态码,并且Size显示from disk cache或from memory cache。强缓存可以通过设置两种 HTTP Header 实现:Expires 和 Cache-Control。
1.Expires
缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点。也就是说,Expires=max-age + 请求时间,需要和Last-modified结合使用。Expires是Web服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。
Expires 是 HTTP/1 的产物,受限于本地时间,如果修改了本地时间,可能会造成缓存失效。Expires: Wed, 22 Oct 2018 08:41:00 GMT表示资源会在 Wed, 22 Oct 2018 08:41:00 GMT 后过期,需要再次请求。
2.Cache-Control
在HTTP/1.1中,Cache-Control是最重要的规则,主要用于控制网页缓存。比如当Cache-Control:max-age=300时,则代表在这个请求正确返回时间(浏览器也会记录下来)的5分钟内再次加载资源,就会命中强缓存。
3.Expires和Cache-Control两者对比
其实这两者差别不大,区别就在于 Expires 是http1.0的产物,Cache-Control是http1.1的产物,两者同时存在的话,Cache-Control优先级高于Expires;在某些不支持HTTP1.1的环境下,Expires就会发挥用处。所以Expires其实是过时的产物,现阶段它的存在只是一种兼容性的写法。
强缓存判断是否缓存的依据来自于是否超出某个时间或者某个时间段,而不关心服务器端文件是否已经更新
协商缓存
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要有以下两种情况:、
1协商缓存生效,返回304和Not Modified
2协商缓存失效,返回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
2.ETag和If-None-Match
Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成。浏览器在下一次加载资源向服务器发送请求时,后台代码会根据不同情况进行控制,会将上一次返回的Etag值放到request header里的If-None-Match里,服务器只需要比较客户端传来的If-None-Match跟自己服务器上该资源的ETag是否一致,就能很好地判断资源相对客户端而言是否被修改过了。如果服务器发现ETag匹配不上,那么直接以常规GET 200回包形式将新的资源(当然也包括了新的ETag)发给客户端;如果ETag是一致的,则直接返回304知会客户端直接使用本地缓存即可
两者之间对比:
首先在精确度上,Etag要优于Last-Modified。
Last-Modified的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的Last-Modified其实并没有体现出来修改,但是Etag每次都会改变确保了精度;如果是负载均衡的服务器,各个服务器生成的Last-Modified也有可能不一致。
第二在性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值。
第三在优先级上,服务器校验优先考虑Etag
七、实际场景应用缓存策略
1.频繁变动的资源
Cache-Control: no-cache
对于频繁变动的资源,首先需要使用Cache-Control: no-cache 使浏览器每次都请求服务器,然后配合 ETag 或者 Last-Modified 来验证资源是否有效。这样的做法虽然不能节省请求数量,但是能显著减少响应数据大小。
2.不常变化的资源
Cache-Control: max-age=31536000
通常在处理这类资源时,给它们的 Cache-Control 配置一个很大的 max-age=31536000 (一年),这样浏览器之后请求相同的 URL 会命中强制缓存。而为了解决更新的问题,就需要在文件名(或者路径)中添加 hash, 版本号等动态字符,之后更改动态字符,从而达到更改引用 URL 的目的,让之前的强制缓存失效 (其实并未立即失效,只是不再使用了而已)。
在线提供的类库 (如 jquery-3.3.1.min.js, lodash.min.js 等) 均采用这个模式。
八、用户行为对浏览器缓存的影响
所谓用户行为对浏览器缓存的影响,指的就是用户在浏览器如何操作时,会触发怎样的缓存策略。主要有 3 种:
打开网页,地址栏输入地址: 查找 disk cache 中是否有匹配。如有则使用;如没有则发送网络请求。
普通刷新 (F5):因为 TAB 并没有关闭,因此 memory cache 是可用的,会被优先使用(如果匹配的话)。其次才是 disk cache。
强制刷新 (Ctrl + F5):浏览器不使用缓存,因此发送的请求头部均带有 Cache-control: no-cache(为了兼容,还带了 Pragma: no-cache),服务器直接返回 200 和最新内容。
-
深入理解浏览器的缓存机制
2021-06-09 00:13:36一、前言关于页面性能优化,浏览器缓存必定是一个绕不过的话题,判断一个网站的性能最直观的就是看网页打开的速度,而提高网页反应速度的一个方式就是使用缓存。一个优秀的缓存策略可以缩短网页请求资源...一、前言
关于页面性能优化,浏览器缓存必定是一个绕不过的话题,判断一个网站的性能最直观的就是看网页打开的速度,而提高网页反应速度的一个方式就是使用缓存。一个优秀的缓存策略可以缩短网页请求资源的距离,减少延迟,并且由于缓存文件可以重复利用,还可以减少带宽,降低网络负荷。因此理解浏览器的缓存机制,就显得尤为重要。
二、缓存类型
缓存在宏观上可以分成两类:私有缓存和共享缓存。共享缓存就是那些能被各级代理缓存的缓存。私有缓存就是用户专享的,各级代理不能缓存的缓存。
微观上可以分下面几类:
1.浏览器缓存
缓存存在的意义就是当用户点击back按钮或是再次去访问某个页面的时候能够更快的响应。尤其是在多页应用的网站中,如果你在多个页面使用了一张相同的图片,那么缓存这张图片就变得特别的有用。浏览器先向代理服务器发起Web请求,再将请求转发到源服务器。其中浏览器缓存包括强缓存和协商缓存,下文有详细介绍。本文主要侧重点就是针对于浏览器缓存。
2.CDN缓存
CDN缓存一般是由网站管理员自己部署,为了让他们的网站更容易扩展并获得更好的性能。通常情况下,浏览器先向CDN网关发起Web请求,网关服务器后面对应着一台或多台负载均衡源服务器,会根据它们的负载请求,动态将请求转发到合适的源服务器上。从浏览器角度来看,整个CDN就是一个源服务器,从这个层面来说,浏览器和服务器之间的缓存机制,在这种架构下同样适用。
3.代理服务器缓存
代理服务器是浏览器和源服务器之间的中间服务器,代理转发响应时,缓存代理会预先将资源的副本(缓存)保存到代理服务器上。当代理再次接收到对相同资源的请求时,就可以不从源服务器那里获取资源,而是将之前缓存的资源作为响应返回。
4.数据库缓存
数据库缓存是指,当web应用的关系比较复杂,数据库中的表很多的时候,如果频繁进行数据库查询,很容易导致数据库不堪重荷。为了提供查询的性能,将查询后的数据放到内存中进行缓存,下次查询时,直接从内存缓存直接返回,提供响应效率。
5.应用层缓存
应用层缓存是指我们在代码层面上做的缓存。通过代码逻辑,把曾经请求过的数据或资源等,缓存起来,再次需要数据时通过逻辑上的处理选择可用的缓存的数据。
三、缓存过程分析
浏览器与服务器通信的方式为应答模式,即是:浏览器发起HTTP请求 – 服务器响应该请求,那么浏览器怎么确定一个资源该不该缓存,如何去缓存呢?浏览器第一次向服务器发起该请求后拿到请求结果后,将请求结果和缓存标识存入浏览器缓存,浏览器对于缓存的处理是根据第一次请求资源时返回的响应头来确定的。具体过程如下图:
由上图我们可以知道:
浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中
以上两点结论就是浏览器缓存机制的关键,它确保了每个请求的缓存存入与读取,只要我们再理解浏览器缓存的使用规则,那么所有的问题就迎刃而解了,本文也将围绕着这点进行详细分析。为了方便大家理解,这里我们根据是否需要向服务器重新发起HTTP请求将缓存过程分为两个部分,分别是强缓存和协商缓存。
四、强缓存
强缓存:不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的network选项中可以看到该请求返回200的状态码,并且size显示from disk cache或from memory cache。
状态码为灰色的请求则代表使用了强制缓存,请求对应的Size值则代表该缓存存放的位置,分别为from memory cache 和 from disk cache。这里或许小伙伴会有这样的疑惑:
from memory cache 和 from disk cache又分别代表的是什么呢?什么时候会使用from disk cache,什么时候会使用from memory cache呢?from memory cache代表使用内存中的缓存,from disk cache则代表使用的是硬盘中的缓存,浏览器读取缓存的顺序为memory –> disk。在浏览器中,浏览器会在js和图片等文件解析执行后直接存入内存缓存中,那么当刷新页面时只需直接从内存缓存中读取(from memory cache);而css文件则会存入硬盘文件中,所以每次渲染页面都需要从硬盘读取缓存(from disk cache)。
相关的header:
Expires:response header里的过期时间,浏览器再次加载资源时,如果在这个过期时间内,则命中强缓存。它的值为一个绝对时间的GMT格式的时间字符串, 比如Expires:Thu,21 Jan 2018 23:39:02 GMT
Cache-Control :在HTTP/1.1中,Cache-Control是最重要的规则,主要用于控制网页缓存。比如当Cache-Control:max-age=300时,则代表在这个请求正确返回时间(浏览器也会记录下来)的5分钟内再次加载资源,就会命中强缓存。常见有以下六个属性值:public:所有内容都将被缓存(客户端和代理服务器都可缓存)。具体来说响应可被任何中间节点缓存,如 Browser <-- proxy1 <-- proxy2 <-- Server,中间的proxy可以缓存资源,比如下次再请求同一资源proxy1直接把自己缓存的东西给 Browser 而不再向proxy2要。
private:所有内容只有客户端可以缓存,Cache-Control的默认取值。具体来说,表示中间节点不允许缓存,对于Browser <-- proxy1 <-- proxy2 <-- Server,proxy 会老老实实把Server 返回的数据发送给proxy1,自己不缓存任何数据。当下次Browser再次请求时proxy会做好请求转发而不是自作主张给自己缓存的数据。
no-cache:客户端缓存内容,是否使用缓存则需要经过协商缓存来验证决定。表示不使用 Cache-Control的缓存控制方式做前置验证,而是使用 Etag 或者Last-Modified字段来控制缓存。需要注意的是,no-cache这个名字有一点误导。设置了no-cache之后,并不是说浏览器就不再缓存数据,只是浏览器在使用缓存数据时,需要先确认一下数据是否还跟服务器保持一致。
no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存
max-age:max-age=xxx (xxx is numeric)表示缓存内容将在xxx秒后失效
s-maxage(单位为s):同max-age,只用于共享缓存(比如CDN缓存)。比如当s-maxage=60时,在这60秒中,即使更新了CDN的内容,浏览器也不会进行请求。max-age用于普通缓存,而s-maxage用于代理缓存。s-maxage的优先级高于max-age。如果存在s-maxage,则会覆盖掉max-age和Expires header。
Expires和Cache-Control两者对比:其实这两者差别不大,区别就在于 Expires 是http1.0的产物,Cache-Control是http1.1的产物,两者同时存在的话,Cache-Control优先级高于Expires;在某些不支持HTTP1.1的环境下,Expires就会发挥用处。所以Expires其实是过时的产物,现阶段它的存在只是一种兼容性的写法。强缓存判断是否缓存的依据来自于是否超出某个时间或者某个时间段,而不关心服务器端文件是否已经更新,这可能会导致加载文件不是服务器端最新的内容,那我们如何获知服务器端内容是否已经发生了更新呢?此时我们需要用到协商缓存策略。
五、协商缓存
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要有以下两种情况:
协商缓存生效,返回304和Not Modified
协商缓存失效,返回200和请求结果
相关的header:
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 存在一些缺点:①某些服务端不能获取精确的修改时间
②文件修改时间改了,但文件内容却没有变
既然根据文件修改时间来决定是否缓存尚有不足,能否可以直接根据文件内容是否修改来决定缓存策略?----ETag和If-None-Match
2.ETag和If-None-Match
Etag是上一次加载资源时,服务器返回的response header,是对该资源的一种唯一标识,只要资源有变化,Etag就会重新生成。浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到request header里的If-None-Match里,服务器只需要比较客户端传来的If-None-Match跟自己服务器上该资源的ETag是否一致,就能很好地判断资源相对客户端而言是否被修改过了。如果服务器发现ETag匹配不上,那么直接以常规GET 200回包形式将新的资源(当然也包括了新的ETag)发给客户端;如果ETag是一致的,则直接返回304知会客户端直接使用本地缓存即可。
两者之间对比:
首先在精确度上,Etag要优于Last-Modified。Last-Modified的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的Last-Modified其实并没有体现出来修改,但是Etag每次都会改变确保了精度;如果是负载均衡的服务器,各个服务器生成的Last-Modified也有可能不一致。第二在性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值。第三在优先级上,服务器校验优先考虑Etag
六、缓存的机制
强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,返回200,重新返回资源和缓存标识,再存入浏览器缓存中;生效则返回304,继续使用缓存。具体流程图如下:
七、用户行为对浏览器缓存的影响
如果资源已经被浏览器缓存下来,在缓存失效之前,再次请求时,默认会先检查是否命中强缓存,如果强缓存命中则直接读取缓存,如果强缓存没有命中则发请求到服务器检查是否命中协商缓存,如果协商缓存命中,则告诉浏览器还是可以从缓存读取,否则才从服务器返回最新的资源。这是默认的处理方式,这个方式可能被浏览器的行为改变:
地址栏访问,链接跳转是正常用户行为,将会触发浏览器缓存机制;
F5刷新,浏览器会设置max-age=0,跳过强缓存判断,会进行协商缓存判断;
ctrl+F5刷新,跳过强缓存和协商缓存,直接从服务器拉取资源。
作者:浪里行舟 https://segmentfault.com/a/1190000017004307
-
【浏览器】浏览器缓存
2021-04-01 16:29:44协商缓存:强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程 缓存策略通过设置HTTP Header来实现的。 - 获取资源形式 状态码 发送请求到服务器 相关设置字段 ...一 浏览器缓存机制
浏览器在每次发生请求时,先在在浏览器缓存中查找该请求的结果和缓存标识,并且每次收到请求结果均会把请求结果和缓存标识保存在浏览器缓存中。
总体脑图:文中脑图及流程图资源
浏览器缓存策略分类
缓存策略的分类:
- 强缓存:不会向服务器发送请求,直接从缓存中读取资源。
- 协商缓存:强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程
缓存策略通过设置
HTTP Header
来实现的。- 获取资源形式 状态码 发送请求到服务器 相关设置字段 强缓存 从缓存取 200(from cache) 否,直接从缓存取 expires,cache-control。如果cache-control与expires同时存在的话,cache-control的优先级高于expires 协商缓存 从缓存取 304(not modified) 是,通过服务器来告知缓存是否可用 Last-Modified/If-Modified-Since,Etag/If-None-Match 浏览器缓存的基本流程:
- 浏览器发送
http
请求前,先访问浏览器缓存,有缓存则进行下一步,否则,进行第5步; - 在浏览器缓存中查找该请求的结果以及缓存标识: 若请求头包含
expires
和cache-control
,则为强缓存策略:根据根据cache-contrle:max-age=xxxx
(优先)、expires
计算缓存时间,若未超时,则进行第4步,若超时则强制缓存实效,进行下一步; - 浏览器会发送请求,若请求头未包含的
etag
、last-modified
,则进行第5步;否则判断为协商缓存,执行协商流程判定:
1). 浏览器首次获取某个资源的时候,服务器会在返回资源的同时在响应头部加上Etag
(资源的唯一标识字符串)、Last-Modified
(资源最后一次在服务器上被修改的时间);
2). 当浏览器再次请求该资源的时候,会在请求头加上If-None-Match
字段(值为1)
中Etag
值)、If-Modified-Since
(值为1)
中Last-Modified
值)
3). 服务器收到传过来的值,再次生成该资源得Etag
,并判定Etag
与If-None-Match
、该资源服务器上的最后修改时间与If-Modified-Since
是否相等,如果相同,则满足协商缓存进行第5步。
4). 如果不满足协商缓存,则进行第6步,更新资源并更新Etag的
值、Last-Modified
的值。 - 从缓存读取,进行第7步;
- 向web服务器发送请求,进行下一步;
- 请求响应,缓存协商,进行下一步;
- 数据展示
流程图:
二 浏览器缓存策略
1 强缓存
强缓存:不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的Network选项中可以看到该请求返回200的状态码,并且Size显示from disk cache或from memory cache。
强缓存可以通过设置两种
HTTP Header
实现:Expires
和Cache-Control
。Expires
Expires
是HTTP1.0
规范的产物:-
值:是服务器端的具体的时间点;
-
格式:绝对时间的GMT格式的时间字符串:
Expires: Wed, 22 Oct 2021 18:41:00 GMT
表示资源会在Wed, 22 Oct 2021 18:41:00 GMT
后过期,需要再次请求。 -
Expires
控制缓存的原理:使用客户端的时间与服务端返回的时间做对比,如果客户端与服务端的时间由于某些原因(时区不同、客户端和服务端有一方的时间不准确)发生误差,那么强制缓存直接失效,那么强制缓存存在的意义就毫无意义。 -
到了HTTP/1.1,
Expires
已经被Cache-Contro
l替代,且现在浏览器的默认使用的是HTTP/1.1网页的response headers部分如下:优先考虑
max-age
,则示资源可以被缓存的最长时间为691200秒cache-control:max-age=691200 expires: Wed, 22 Oct 2021 18:41:00 GMT
Cache-Control
在HTTP/1.1中,
Cache-Control
是最重要的规则,主要用于控制网页缓存。- 值:一个相对时间。比如当
Cache-Control:max-age=300
时,则代表在这个请求正确返回时间(浏览器也会记录下来)的300s内再次加载资源,就会命中强缓存,直接从缓存中获取资源; - 格式:数字,单位
s
; Cache-Control
控制缓存的原理: 超时时间截点 = 资源返回时间+Cache-Control
的相对时间。Cache-Control
可以在请求头或者响应头中设置,并且可以组合使用多种指令:
指令 作用 public 表示响应可以被客户端和CDN等代理服务器缓存 private 表示响应只可以被客户端缓存,Cache-Control的默认取值 max-age=30 缓存30s后就过期,需要重新请求 s-maxage=30 优先级高于max-age,存在时会覆盖max-age,作用一样,只在代理服务器中生效,ax-age用于普通缓存,而s-maxage用于代理缓存。 no-store 不缓存任何响应,即不使用强制缓存,也不使用协商缓存 no-cache 资源被客户端缓存,是否使用缓存则需要经过协商缓存来验证决定。表示不使用 Cache-Control的缓存控制方式做前置验证,而是使用 Etag 或者Last-Modified字段来控制缓存。 max-stale=30 能容忍的最大过期时间。30s秒内,即使缓存过期,也使用该缓存 min-fresh=30 能够容忍的最小新鲜度。希望在30s内获取最新的响应 Expires和Cache-Control两者对比:
Cache-Control
优先级高于Expires
;在某些不支持HTTP1.1的环境下,Expires就会发挥用处。强缓存判断是否缓存的依据来自于是否超出某个时间或者某个时间段,而不关心服务器端文件是否已经更新,这可能会导致加载文件不是服务器端最新的内容,那我们如何获知服务器端内容是否已经发生了更新呢?此时我们需要用到协商缓存策略。
2 协商缓存
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要有以下两种情况:
- 协商缓存生效,返回304和Not Modified
- 协商缓存失效,返回200和请求结果
协商缓存的标识也是在响应报文的HTTP头中和请求结果一起返回给浏览器的,控制协商缓存的字段分别有:
Last-Modified / If-Modified-Since
和Etag / If-None-Match
,其中Etag / If-None-Match
的优先级比Last-Modified / If-Modified-Since
高。Last-Modified
和If-Modified-Since
Last-Modified
是服务器响应请求时,返回该资源文件在服务器最后被修改的时间。浏览器在第一次访问资源时,在response header
中添加Last-Modified
到header
,浏览器接收后缓存文件和 header;Last-Modified: Fri, 22 Jul 2021 01:47:00 GMT
If-Modified-Since
则是客户端再次发起该请求时,携带上次请求返回的Last-Modified
值,通过此字段值告诉服务器该资源上次请求返回的最后被修改时间。服务器收到该请求,发现请求头含有If-Modified-Since
字段,则会对比If-Modified-Since
的字段值与该资源在服务器的最后被修改时间,若服务器的资源最后被修改时间大于If-Modified-Since
的字段值,则重新返回资源,状态码为200;否则则返回304,代表资源无更新,可继续使用缓存文件,If-Modified-Since: Fri, 21 Jul 2021 01:47:00 GMT
但是 Last-Modified 存在一些弊端:
- 如果本地打开缓存文件,即使没有对文件进行修改,但还是会造成
Last-Modified
被修改,服务端不能命中缓存导致发送相同的资源 - 因为 Last-Modified 只能以秒计时,如果在不可感知的时间内修改完成文件,那么服务端会认为资源还是命中了,不会返回正确的资源
既然根据文件修改时间来决定是否缓存尚有不足,能否可以直接根据文件内容是否修改来决定缓存策略?所以在 HTTP / 1.1 出现了 ETag 和 If-None-Match
ETag
和If-None-Match
Etag
是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成。etag: W/"4d24eb245e63692a52bd1ef1a26b09ad079eacd16becfff8e655bb1b809b98f8"
If-None-Match
是客户端再次发起该请求时,携带上次请求返回的唯一标识Etag
值,通过此字段值告诉服务器该资源上次请求返回的唯一标识值。服务器收到该请求后,发现该请求头中含有If-None-Match
,则会根据If-None-Match
的字段值与该资源在服务器的Etag值做对比,一致则返回304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为200,如下。if-none-match: W/"4d24eb245e63692a52bd1ef1a26b09ad079eacd16becfff8e655bb1b809b98f8"
- 两者之间对比:
-
首先在精确度上,Etag要优于Last-Modified。
Last-Modified的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的Last-Modified其实并没有体 现出来修改,但是Etag每次都会改变确保了精度;如果是负载均衡的服务器,各个服务器生成的Last- Modified也有可能不一致。 -
第二在性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值。
-
第三在优先级上,服务器校验优先考虑Etag
3 缓存机制
强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,返回200,重新返回资源和缓存标识,再存入浏览器缓存中;生效则返回304,继续使用缓存。
三、缓存位置
清楚了浏览器缓存的过程,那么浏览器缓存的存储位置都有哪几种呢?浏览器的缓存,按照其缓存位置可以分为四种:
- Service Worker
- Memory Cache
- Disk Cache
- Push Cache
从缓存位置上来说分为四种,并且各自有优先级,当依次查找缓存且都没有命中的时候,才会去请求网络。
-
Service Worker
Service Worker 是运行在浏览器背后的独立线程,一般可以用来实现缓存功能。使用 Service Worker的话,传输协议必须为 HTTPS。因为 Service Worker 中涉及到请求拦截,所以必须使用 HTTPS 协议来保障安全。Service Worker 的缓存与浏览器其他内建的缓存机制不同,它可以让我们自由控制缓存哪些文件、如何匹配缓存、如何读取缓存,并且缓存是持续性的。Service Worker 实现缓存功能一般分为三个步骤:首先需要先注册 Service Worker,然后监听到 install 事件以后就可以缓存需要的文件,那么在下次用户访问的时候就可以通过拦截请求的方式查询是否存在缓存,存在缓存的话就可以直接读取缓存文件,否则就去请求数据。
当 Service Worker 没有命中缓存的时候,我们需要去调用 fetch 函数获取数据。也就是说,如果我们没有在 Service Worker 命中缓存的话,会根据缓存查找优先级去查找数据。但是不管我们是从 Memory Cache 中还是从网络请求中获取的数据,浏览器都会显示我们是从 Service Worker 中获取的内容。
-
Memory Cache
Memory Cache 也就是内存中的缓存,主要包含的是当前中页面中已经抓取到的资源,例如页面上已经下载的样式、脚本、图片等。读取内存中的数据肯定比磁盘快,内存缓存虽然读取高效,可是缓存持续性很短,会随着进程的释放而释放。 一旦我们关闭 Tab 页面,内存中的缓存也就被释放了。那么既然内存缓存这么高效,我们是不是能让数据都存放在内存中呢?
这是不可能的。计算机中的内存一定比硬盘容量小得多,操作系统需要精打细算内存的使用,所以能让我们使用的内存必然不多。当我们访问过页面以后,再次刷新页面,可以发现很多数据都来自于内存缓存
内存缓存中有一块重要的缓存资源是preloader相关指令(例如)下载的资源。总所周知preloader的相关指令已经是页面优化的常见手段之一,它可以一边解析js/css文件,一边网络请求下一个资源。
需要注意的事情是,内存缓存在缓存资源时并不关心返回资源的HTTP缓存头Cache-Control是什么值,同时资源的匹配也并非仅仅是对URL做匹配,还可能会对Content-Type,CORS等其他特征做校验。
-
Disk Cache
Disk Cache 也就是存储在硬盘中的缓存,读取速度慢点,但是什么都能存储到磁盘中,比之 Memory Cache 胜在容量和存储时效性上。在所有浏览器缓存中,Disk Cache 覆盖面基本是最大的。它会根据 HTTP Herder 中的字段判断哪些资源需要缓存,哪些资源可以不请求直接使用,哪些资源已经过期需要重新请求。并且即使在跨站点的情况下,相同地址的资源一旦被硬盘缓存下来,就不会再次去请求数据。绝大部分的缓存都来自 Disk Cache,关于 HTTP 的协议头中的缓存字段,我们会在下文进行详细介绍。
浏览器会把哪些文件丢进内存中?哪些丢进硬盘中?
关于这点,网上说法不一,不过以下观点比较靠得住:
- 对于大文件来说,大概率是不存储在内存中的,反之优先
- 当前系统内存使用率高的话,文件优先存储进硬盘 -
Push Cache
Push Cache(推送缓存)是 HTTP/2 中的内容,当以上三种缓存都没有命中时,它才会被使用。它只在会话(Session)中存在,一旦会话结束就被释放,并且缓存时间也很短暂,在Chrome浏览器中只有5分钟左右,同时它也并非严格执行HTTP头中的缓存指令。Push Cache 在国内能够查到的资料很少,也是因为 HTTP/2 在国内不够普及。这里推荐阅读Jake Archibald的 HTTP/2 push is tougher than I thought 这篇文章,文章中的几个结论:
- 所有的资源都能被推送,并且能够被缓存,但是 Edge 和 Safari 浏览器支持相对比较差
- 可以推送 no-cache 和 no-store 的资源
- 一旦连接被关闭,Push Cache 就被释放
- 多个页面可以使用同一个HTTP/2的连接,也就可以使用同一个Push Cache。这主要还是依赖浏览器的实现而定,出于对性能的考虑,有的浏览器会对相同域名但不同的tab标签使用同一个HTTP连接。
- Push Cache 中的缓存只能被使用一次
- 浏览器可以拒绝接受已经存在的资源推送
- 你可以给其他域名推送资源
如果以上四种缓存都没有命中的话,那么只能发起请求来获取资源了。
那么为了性能上的考虑,大部分的接口都应该选择好缓存策略,
访问缓存优先级(三级缓存原理 )- 先在内存中查找,如果有,直接加载。
- 如果内存中不存在,则在硬盘中查找,如果有直接加载。
- 如果硬盘中也没有,那么就进行网络请求。
- 请求获取的资源缓存到硬盘和内存。
在chrome浏览器中的控制台Network中size栏通常会有三种状态
- from memory cache:从内存中拿到的资源
- from disk cache:从磁盘中读取到的资源
- 资源本身大小数值:当http状态为200是实实在在从浏览器获取的资源,当http状态为304时该数字是与服务端通信报文的大小,并不是该资源本身的大小,该资源是从本地获取的
状态 类型 说明 200 form memory cache 不请求网络资源,资源在内存当中,一般脚本、字体、图片会存在内存当中。 200 form disk ceche 不请求网络资源,在磁盘当中,一般非脚本会存在内存当中,如css等。 200 资源大小数值 资源大小数值 从服务器下载最新资源。 304 报文大小 请求服务端发现资源没有更新,使用本地资源,即命中协商缓存。 四 实际场景应用缓存策略
1.频繁变动的资源:
Cache-Control: no-cache
对于频繁变动的资源,首先需要使用Cache-Control: no-cache 使浏览器每次都请求服务器,然后配合 ETag 或者 Last-Modified 来验证资源是否有效。这样的做法虽然不能节省请求数量,但是能显著减少响应数据大小。
2.不常变化的资源:
Cache-Control: max-age=31536000
通常在处理这类资源时,给它们的 Cache-Control 配置一个很大的 max-age=31536000 (一年),这样浏览器之后请求相同的 URL 会命中强制缓存。而为了解决更新的问题,就需要在文件名(或者路径)中添加 hash, 版本号等动态字符,之后更改动态字符,从而达到更改引用 URL 的目的,让之前的强制缓存失效 (其实并未立即失效,只是不再使用了而已)。
在线提供的类库 (如 jquery-3.3.1.min.js, lodash.min.js 等) 均采用这个模式。五 用户行为对缓存的影响:
所谓用户行为对浏览器缓存的影响,指的就是用户在浏览器如何操作时,会触发怎样的缓存策略。主要有 3 种:- 打开网页,地址栏输入地址: 查找 disk cache 中是否有匹配。如有则使用;如没有则发送网络请求。
- 普通刷新 (F5):因为 TAB 并没有关闭,因此 memory cache 是可用的,会被优先使用(如果匹配的话)。其次才是 disk cache。
- 强制刷新 (Ctrl + F5):浏览器不使用缓存,因此发送的请求头部均带有 Cache-control: no-cache(为了兼容,还带了 Pragma: no-cache),服务器直接返回 200 和最新内容
参考:
- HTTP强缓存和协商缓存https://segmentfault.com/a/1190000008956069
- 深入理解浏览器的缓存机制 https://www.jianshu.com/p/54cc04190252
- 彻底理解浏览器的缓存机制(http缓存机制)https://www.mwcxs.top/page/565.html
-
HTTP缓存-http强制缓存与协商缓存
2022-02-13 23:27:00缓存介绍 缓存的原理:在首次请求后保存一份请求资源的响应副本,当用户再次发起相同请求后,如果判断缓存命中则拦截请求,将之前存储的响应...HTTP 缓存可细分为强制缓存与协商缓存。 强制缓存:不用判断缓存是否过期 -
协商缓存和强缓存
2022-03-17 13:16:14强缓存就是强制缓存的意思,当浏览器去请求某个文件时,服务端就在返回头中对该文件进行了缓存配置 response header中 cache-control 常见的设置是max-age public private no-cache no-store max-age 表示缓存 -
强缓存和协商缓存
2022-02-25 15:16:21强缓存和协商缓存 -
Js篇-面试题6-聊一下强缓存与协商缓存
2020-09-05 08:00:00缓存的时间、缓存类型都由服务端控制 浏览器第一次请求时 浏览器后续在进行请求时 从上图可以知道,浏览器缓存包括两种类型,即强缓存(本地缓存)和协商缓存,浏览器在第一次请求发生后,再次请求时 浏览器在请求某一资源... -
HTTP缓存——协商缓存(缓存验证)
2021-09-23 06:14:49协商缓存 所谓“协商”,可以理解为:客户端和服务端双方商量着来。 客户端检查资源超过有效期、强缓存命中失败的情况下,则发出请求“询问”服务器是否资源真的过期了,询问的同时在请求头要携带着资源的「上次更新... -
通过 Node.js 实践彻底搞懂强缓存和协商缓存
2021-03-26 00:20:45浏览器缓存是性能优化非常重要的一个方案,合理地使用缓存可以提高用户体验,还能节省服务器的开销。掌握好缓存的原理和并合理地使用无论对前端还是运维都是相当重要的。什么是浏览器缓存浏览器缓存(h... -
浏览器缓存
2022-01-16 20:54:03一、浏览器缓存基本认识 ...当强缓存没有命中的时候,浏览器一定会发送一个请求到服务器,通过服务器端依据资源的另外一些http header验证这个资源是否命中协商缓存,如果协商缓存命中,服务器会将这. -
javaWeb之利用Filter(过滤器)实现禁用浏览器缓存功能
2019-07-22 13:29:25什么是浏览器缓存 浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这就是浏览器缓存。 为什么使用浏览器缓存? 对于浏览器缓存,相信大家都不会陌生... -
服务器设置浏览器是否缓存
2019-07-09 17:45:22好长时间没有更新文章了,发现多了几位小粉丝,正好今天 遇到一个问题,关于浏览器缓存的问题,那就分享给你们! ( 题外话 :安利一首 刘德华的 《十七...3.浏览器缓存、HTTP缓存(强缓存、协商缓存),浏览器缓存和... -
浏览器缓存浅析
2022-02-10 15:10:28当下一个请求到来的时候,如果是相同的URL,浏览器会根据缓存机制决定是直接使用副本响应访问请求还是向源服务器再次发起请求。 使用缓存的原因 (1)减少网络带宽消耗:当web缓存副本被使用时,只会产生极小的网络... -
面试官问我:说说你对浏览器缓存的理解
2021-03-11 11:08:57缓存类型强缓存定义:当发起HTTP请求时,不会向服务器进行请求,只要当前时间在缓存有效期内,则直接从客户端缓存中获得,当缓存过期之后,才会真正想服务器发起请求重新获得资源。特征打开开发者工具,从Network中... -
设置响应头控制浏览器的缓存
2019-09-29 03:55:46主要用于客户端(浏览器)向服务器端请求的是一些比较大的数据,并且这个数据在短时间内不会经常发生变化的情况,比如一些网站的logo图片,它是一个网站的标志,一般不会发生变化,如果不缓存的话,而logo图片又比较... -
前端浏览器缓存知识梳理
2021-06-05 00:53:01公众号关注“前端开发博客”设为 “星标”,每天分享一个前端知识点!在前端性能优化的方式中,最重要的当然是缓存了,使用好了缓存,对项目有很大的帮助。比如我们访问网页时,使用网页后退功能,会... -
Java缓存学习:CDN缓存机制
2021-12-15 15:58:23按F5或浏览器刷新按钮 浏览器会在请求中附加必要的缓存协商,但不允许浏览器直接使用本地缓存,它能够让 Last-Modified、ETag发挥效果,但是对Expires无效。 3. 按Ctrl+F5或按Ctrl并点击刷新按钮 这种方式就是强制... -
一篇关于浏览器缓存知识的梳理
2021-06-07 00:01:59来源:黑色的枫https://juejin.cn/post/6947936223126093861在前端性能优化的方式中,最重要的当然是缓存了,使用好了缓存,对项目有很大的帮助。比如我们访... -
浏览器缓存原理总结
2019-03-19 17:29:56分为强缓存和协商缓存 1、浏览器在加载资源时,先根据这个资源的一些http header判断它是否命中强缓存,强缓存如果命中,浏览器直接从自己的缓存中读取资源,不会发请求到服务器。比如某个css文件,如果浏览器在... -
【浏览器】973- 前端浏览器缓存知识梳理
2021-06-07 00:18:51来源:黑色的枫https://juejin.cn/post/6947936223126093861在前端性能优化的方式中,最重要的当然是缓存了,使用好了缓存,对项目有很大的帮助。比如我们访... -
DNS 缓存、CDN 缓存、浏览器缓存,JVM DNS 缓存详解
2021-04-16 14:30:54最近测试遇到修改host文件后,清除浏览器缓存后,重启浏览器后,发现浏览器还是访问老DNS服务,于是网上查查原因,豁然开朗。 这里对互联网上一些文章进行整理,原文可查看参。 1、DNS 缓存 1.1 什么是DNS ... -
协商缓存和强制缓存
2019-05-21 10:19:57《协商缓存和强制缓存》 1. 背景介绍 做前端有两个比较令人头痛的事,一个是命名,另一个就是缓存了。HTTP 协议提供了非常强大的缓存机制, 了解这些缓存机制,对提高网站的性能非常有帮助。 2. 知识剖析 ... -
彻底理解浏览器的Http缓存机制
2020-08-01 17:55:56浏览器的缓存机制也就是我们说的HTTP缓存机制,其机制是根据HTTP报文的缓存标识进行的,所以在分析浏览器缓存机制之前,我们先使用图文简单介绍一下HTTP报文,HTTP报文分为两种:HTTP请求(Request)报文,报文格式为... -
彻底弄懂浏览器缓存策略
2020-07-15 19:01:21作者:kevinylzhao,腾讯音乐前端开发工程师浏览器缓存策略对于前端开发同学来说不陌生,大家都有一定的了解,但如果没有系统的归纳总结,可能三言两语很难说明白,甚至说错,尤其在面试过... -
java web开发中常用的协议的使用和java-web 常见的缓存技术
2021-02-12 19:35:45java dns 域名解析协议实现1 域名解析,将域名可转换为ip地址InetAddress也可以通过使用getAddress()来获得IP地址,但是它的返回值是一个4个字节的数组。因此尽管getAddress()在获得IP方面是有用的,但却不适于用来... -
Java性能优化十七、缓存优化
2021-07-08 09:54:24文章目录缓存优化一、如何使用缓存优化系统性能1、前端缓存技术1. 本地缓存2.网关缓存2、服务层缓存技术1.进程缓存2.分布式缓存3、数据库与缓存数据一致性问题4、缓存穿透、缓存击穿、缓存雪崩总结二、双十一抢购... -
22、浏览器缓存机制
2021-03-17 22:06:0522.1 浏览器缓存机制 注意:该知识点属于性能优化领域,并且整一章节都是一个面试题 缓存可以说是性能优化中简单高效的一种优化方式了,它可以显著减少网络传输所带来的损耗。 对于一个数据请求来说,可以分为...