浏览器Disk Cache磁盘缓存及其协商缓存、及原生App和浏览器实现缓存的差异
目录
浏览器Disk Cache磁盘缓存及其协商缓存、及原生App和浏览器实现缓存的差异
2.4、Disk Cache(与http指令的cache匹配,故又名Http Cache)
3.2.1、当被浏览器“强制缓存”的资源,在服务端发生“Modified”改变时,浏览器这一侧,缓存将如何“更新”;
3.2.2、当被浏览器“强制缓存”的资源,在服务端是否可以给定一个“过期”的机制,过期后,浏览器这一侧,该如何处理,且如何如何“更新”缓存;
3.2.3、浏览器的“导航器”或“浏览器的内置js解释器引擎”,首次处理H5或Http请求的资源时,应当采用什么样的机制。
我们知道,在计算机中,数据存储,要么读写“内存”、要么读写“ 磁盘”,没有第三者。浏览器也不例外,其存取数据,要么读写“内存”、要么读写“磁盘”,也没有第三者。
“缓存”的目的:
无论是web应用,还是原生App应用,无论是在客户端,还是在服务端,应用为了提升执行的效率(体现时间、速度)和节省设备和网络的关键性能指标(比如网络带宽的开销、CPU利用率、内存耗用、硬盘读写的I/O负载)的开销,会考虑将一些“请求”的资源在“内存”中或在“磁盘”中“预备”好,需要的时候,直接提取出来使用,从而减少了:
网络的往返的次数;
数据的重复计算;
数据的重复提取;
数据量的大小。
浏览器“缓存”的目的:
◆ 首先:应当考虑上述“通用”的“缓存”目的;
◆ 其次:是缓解浏览器自身来自“内存”读写的负载的。浏览器内部的“内存管理模块”,会尽可能的使用高速内存以提高效率,当其内部代码逻辑,发现本机内存已吃紧,它会自动启用对“磁盘”储存来进行读写,“磁盘”储存即我们通常所说的“虚拟内存”。
◆ 浏览器利用本机的“虚拟内存”:是操作系统提供的外部存储,用以扩展“内存”的使用,因为它本质上并不是真正的“内存”,所以称为“虚拟”;它是“硬盘”上的“分块”的页面文件,MsWindows的话,将其作为“ROM”来进行使用;“虚拟内存”的速度取决于磁盘I/O,其性能远低于“内存”的I/O。
◆ 浏览器为了简化用户对上述对其内部“对外公开”的“内存”管理功能和“虚拟内存”功能的“引用”,按照www组织的定义,对暴露给用户的“存储”及其关联的“缓存”的概念、分类、功能和用法,进行了进一步的“划分”:
◇ “Service Worker方式的(即PWA的实现的基础)”Cache Storage:
https://developer.chrome.com/docs/devtools/progressive-web-apps/?utm_source=devtools#opaque-responses
◇ “非Service Worker方式的”Cache Storage:
本文实际测试一下浏览器的行为、浏览器的存储、与存储关联的“缓存”。
1、Memory Cache和Disk Cache区别
1.1、Memory Cache
◆浏览器自动的性能行为
◆存储位置:内存的地址及其空间
◆时效性:导航器刷新或浏览器关闭,即刻释放
1.2、Disk Cache
◆总是与Http的“请求-响应”相关
◆存储位置:磁盘中不同类型的存储路径
◆时效性:导航器刷新或浏览器关闭,不受影响
1.2.1、Disk Cache的存取举例
拿MSWindows来举例(不同OS操作系统平台,各异:包括各派别的手机操作系统、各服务器操作系统厂家或发起机构、各PC操作系统厂家或发起机构),存储位置:
我们知道,所有MSWindows应用,其统一的本机“用户数据”的存取路径,均为:
C:\Users\Administrator\AppData\Local\
(除非你修改了操作系统默认的“全局路径”)
现以\Google\Chrome浏览器的\User Data用户数据,默认的Local Storage加密数据举例:
C:\Users\Administrator\AppData\Local\Google\Chrome\User Data\Default\Local Storage\leveldb
它对应了浏览器控制台该位置的数据存取:
(图2)
除此之外,还有各种本机用户的应用的默认数据:
(图3)
“Disk缓存”就是上述的其中一类“用户数据”。
1.2.2、Disk Cache的存取方式
◆要么“用户”与“浏览器”的控制台“交互”(如图2);
◆要么以编程的方式:动态地请求其中的数据,可以是与浏览器相关的API的方式、可以是浏览器原生SDK软件开发包或IDE厂家对SDK编制的API的方式。但,均需受制于必要的“源”的“权限机制”或“征得所有者(用户)的许可”(如图2或图3)。
◆默认是按“源/域”进行分区的
2、缓存,按执行优先级次序分类
◆浏览器的存储about:blank
◆Service Worker
◆Memory Cache
◆Disk Cache(与http的指令cache匹配,故又名Http Cache)
◆Push Cache
◆……等等,其它缓存
现,分别概述一下:
2.1、浏览器存储的自身行为
当“导航器”中首次执行输入的Location的URL地址时,会强制触发Storage下的第一方和第三方的”域/源”、(如果有的话,同时会读写:)及其“Cookies”、“IndexedDB”:
◇Loacal Storage
◇Session Storage
◇Cookies
典型的引用,比如我们用导航器打开“腾讯云”的站点:https://cloud.tencent.com/
2.2、Service Worker
MsWindows下,其物理存取路径为:
C:\Users\Administrator\AppData\Local\Google\Chrome\User Data\Default\Service Worker
按照其Disk Cache缓存内容的不同,分别可以对这些“缓存位置”及其“缓存内容”,进行存取:
其结构如下:
需要注意的是,这个存储大小的配额数值:指的是:
如果使用了service worker并进行了addResourcesToCache缓存操作,在service worker模式下对cache storage的配额是没有限制的。仅仅在:在“非service worker环境”下,在没有使用indexedDB时,单次请求、单个文件的存储,不超过7m/个文件/次请求;
那么,在“非service worker环境”下,超了怎么办?我们应当使用技巧:就是在请求时,将大文件chunk分块成N多个小块文件,每个文件不超过阀值(7M,安全起见,均设置为5M,与普通非SW缓存的使用保持一致);在服务端一次性生成这些文件,客户端一次请求N多个chunked分块。
典型的应用情景,就是“分页”数据的“静默”提取:将“渲染主线程上下文”中所需的“每个分页”数据,在“非渲染主线程上下文”(SW的安全上下文)中一次性地全部分别fetch下来,保存到Cache Storage中,以便“渲染主进程window”中的”worker”(负责渲染的网页)根据需要,从缓存中读取。但是你会发现,如果1个59MB的Json文件,你下载会非常的耗时,而且它被一次性地渲染布局到页面中也会有“卡顿”发生,那么怎么办呢:就是采用上述办法,请求N多个chunked分块,服务端一次性生成这些文件,让“每个分页”只渲染和布局绘制1个chunked分块,这样在Cache Storage体现出来就是所有N个Json文件(每个chunked分片的Json文件大小 = 59MB/N <=5MB),Cache Storage中缓存的“每个Json文件”为“每个分页”提供本机的数据服务。
刷新或再次使用该“资源”,0KB,从磁盘缓存中提取,不再消耗网络和服务器时间(但是本机渲染和布局绘制的时间,仍旧是独立的,需要单独消耗的):
同理,利用“缓存更新技术”:可以比较Cache Storage中存储的数据,和服务端存取的数据,之间的“字节差异”,做客户端的“缓存更新一次性提交客户端维护的变化了的数据”。
◆ SW的Disk Cache:“默认”,是按“源/域”进行分区的,而且是按“顶级文档源”(地址栏中显示的来源);
◆ 当然:你也可以使用“不透明响应”,来绕过这种限制,来实现“跨域安全策略”;
◆ SW:也可以使用IndexedDB存储。
SW,现已被绝大多数浏览器内核,接受并支持,只有少数不支持(注意,不要将PWA和SW划等号,PWA需要依赖SW的技术而已),下图是iPhone 7下iOS 13.6的效果:
◆ 苹果的态度:
从2018年起,Safari Technology Preview 48、macOS High Sierra 10.13.4 beta seed 2 和 iOS 11.3 beta seed 2及其之后,苹果便开始了对serviceWorker的支持和发布。
◆ 苹果对待serviceWorker的观点:Service Worker API是在 WebKit 的多进程基础架构中实现的,它提供了安全性和性能优势。
◆ serviceWorker的启动运行和停止运行的机制:由于 Service Worker 实例同时消耗内存和 CPU 时间,因此仅在需要时运行它们很重要。serviceWorker通常在最初由网页注册时启动。在正常情况下,当一个serviceWorker的分区中没有serviceWorker的客户端,在一个小的宽限期后,serviceWorker将被终止。每当需要一些交互时,serviceWorker都会重新启动。
◆ serviceWorker与存储和缓存:serviceWorker和缓存API存储的信息将随着用户浏览内容而增长。为了只保留对用户有用的存储信息,WebKit 将在几周后(或苹果最新政策规定的时间期限)删除未使用的serviceWorker注册。几周后未打开的缓存也将被删除。Web 应用程序必须对任何被删除的单个缓存、缓存条目或serviceWorker具有弹性。
◆ 苹果Safari浏览器支持对serviceWorker的代码调试debug:
苹果Safari浏览器的Web Inspector 支持调试serviceWorker(若是手机的话,需要手机usb与macOS电脑连调)。“开发”菜单中包含随时运行的serviceWorker列表。单击其中一个 service worker 条目的js时,将附加一个检查员到该serviceWorker。从这里,可以使用断点调试与 fetch 或 postMessage 事件相关的代码。检查器控制台也是使用 fetch API 在serviceWorker上下文中触发网络负载的好地方。也可以通过几行代码从控制台检查 service worker 缓存,比如:
// # 在各个平台通用的调测代码:
await fetch('_index.html')
await self.caches.keys()
cache = await self.caches.open('v1')
await cache.keys()
await cache.matchAll()
◆ iOS在https下支持SW,下图为安装状态:
◆ 下图为已激活状态:
◆ 但是iOS在http下不支持SW(理论上,所有平台SW都应当在https或安全上下文中作业),下图为提示状态:
◆ 总之,一句话,移动端,无论原生App也好、web应用也好,不同平台及其内置浏览器会有许多限制,我是将开发选项中很多,都打开了的;或者通过代码请求权限,拉起提示让“用户”授权:
◆ 检测支持情况,官方推荐站点1:
◆ 检测支持情况,官方推荐站点2:
Is service worker ready?
2.3、Memory Cache
通常,浏览器的导航器,在初次执行window.location的URL时,或重复刷新页面时,会考虑将如下资源优先进行“内存缓存Memory Cache”:
◆html的DOM解构:
优先级,最高,用于渲染、元素本身不缓存:
◆head中的:
优先级,最高:
◇除icon类型的(包括x-icon)以外的<link>资源,特别是style样式表的css文件;
icon类型的<link>资源—属于特殊类型,为Disk Cache(优先级:最高)
◆body中的:
◇页面中直接使用H5原生的fetch的src=”路径”的资源,比如:
优先级(js文件或嵌入script中的js代码)中等:
<script src=”../js/index.js”></script>
优先级(img、音视频类)低:
<img src=”../img/test.png” alt=””>等,再比如:
2.4、Disk Cache(与http指令的cache匹配,故又名Http Cache)
再次执行同样URL的导航window.location,或再次刷新页面,之前的“内存缓存Memory Cache”,将被”强制缓存“至”Disk Cache磁盘缓存”中,并且此时服务端若存在304协商机制的代码,同时”协商缓存”会生效,将其Etag唯一性缓存标识及缓存的Cache-Control过期控制信息返回给浏览器的”Disk Cache磁盘缓存”。
2.5、Push Cache
Push Cache与浏览器的“后端服务”代码相关:
3、Disk Cache缓存,按其功能的类型分类
◆强制缓存
◆协商缓存
3.1、强制缓存
当导航器或http请求,首次执行时,浏览器为了“性能”,首次强行的“缓存”至内存,再次执行相同URL请求时,浏览器“强制缓存”至磁盘。总之,“强制缓存”,是浏览器干出来的,与http和网络,原本并无干系。
3.2、协商缓存
由于浏览器永远都期望强行的进行本机的“缓存”,那么当“资源变化”时,若它也“强制缓存”,那么必然会导致代码与视觉或数据之间“不符合逻辑”,怎么办呢?
代表App的浏览器的厂商,与代表代码的js、html和css的阵营和为html而生的http,它们之间坐下来商议,我们需要出一个“标准”:
为了共同的“性能”的目标,我们之间(浏览器和后端服务代码)需要明确几点:
3.2.1、当被浏览器“强制缓存”的资源,在服务端发生“Modified”改变时,浏览器这一侧,缓存将如何“更新”;
3.2.2、当被浏览器“强制缓存”的资源,在服务端是否可以给定一个“过期”的机制,过期后,浏览器这一侧,该如何处理,且如何如何“更新”缓存;
3.2.3、浏览器的“导航器”或“浏览器的内置js解释器引擎”,首次处理H5或Http请求的资源时,应当采用什么样的机制。
于是,代表这种“提议”的“标准”出来了,即rfc 2616中的“10.3.5 304 Not Modified”及其“关联标准”条目:
◆ If the client has performed a conditional GET request and access is
allowed, but the document has not been modified, the server SHOULD
respond with this status code. The 304 response MUST NOT contain a
message-body, and thus is always terminated by the first empty line
after the header fields.
如果客户端已执行条件GET请求,并且访问是允许的,
但文档还尚未被修改话,服务器应用此状态码进行响应。
304响应不得包含 消息正文message-body,
因此总是在标题字段header fields之后以第一个空行结束first empty line。
◆ The response MUST include the following header fields:
响应必须包括以下标题字段header fields:
◆ – Date, unless its omission is required by section 14.18.1
-日期,除非第14.18.1节“ ClockLess Origin Server Operation无时钟“源”服务器操作”中要求省略
◆ If a ClockLess origin server obeys these rules, and proxies and
clients add their own Date to any response received without one (as
already specified by [RFC 2068], section 14.19), caches will operate
correctly.
如果无时钟源服务器( ClockLess origin server)遵守这些规则,
代理或客户端将它们拥有的“日期Date”添加到接收到的任何没有日期的响应中
(如已由[RFC 2068]第14.19节规定),缓存将正确地运行。
◆ – ETag and/or Content-Location, if the header would have been sent
in a 200 response to the same request
-如果在对同一请求的200的响应中,标题header已经被导航器或代码执行了200 OK的发送,
则标记:ETag和/或Content Location
◆ – Expires, Cache-Control, and/or Vary, if the field-value might
differ from that sent in any previous response for the same
variant
-如果字段值与之前发送的相同响应的变量值不同,可以发送响应头:
过期Expires、缓存控制Cache-Control 和/或 更改Vary
◆ If the conditional GET used a strong cache validator (see section
13.3.3), the response SHOULD NOT include other entity-headers.
Otherwise (i.e., the conditional GET used a weak validator), the
response MUST NOT include other entity-headers; this prevents
inconsistencies between cached entity-bodies and updated headers.
如果条件GET使用了“强制缓存”验证器strong cache validator(请参阅第节13.3.3),
响应不应包括其他实体标头entity-headers。
否则(比如:条件GET使用“弱”验证器weak validator)响应不得包含其他实体标头;
这可以防止“缓存的实体主体cached entity-bodies”和“更新的标头updated headers”之间的不一致。
◆ If a 304 response indicates an entity not currently cached, then the
cache MUST disregard the response and repeat the request without the
conditional.
如果304响应指示当前实体未被缓存,则缓存必须并且是无条件地忽略响应
◆ If a cache uses a received 304 response to update a cache entry, the
cache MUST update the entry to reflect any new field values given in
the response.
如果缓存使用接收到的304响应来更新缓存条目,缓存必须更新条目以反映给定的响应中的任何新字段值。
概括起来,“协商”三条,即为“协商缓存”:
为了共同的“性能”和“可用性”的目标,“浏览器联盟一方”同“后端服务开发联盟和http网络一方”,一致明确了,如下的”w3c执行标准”:
3.2.1、当被浏览器“强制缓存”的资源,再次请求“相同资源”时(即请求的URL不变),无论服务端的资源的名称或字节数是否变化,均需要“在本机做验证和效验”Etag标识及其对应的Control-Cache: max-age=***毫秒,must-revalidate: true的是否过期且重新验证的信息,效验该资源是否有效或过期:若未过期,则无需重新请求“服务端”,直接使用“本机缓存”的内容加载、渲染并绘制页面;若过期或无效,则浏览器让客户端的代码,重新发起“资源的网络请求”、“在服务端做验证和效验”处理,并据此重新“更新本机的缓存”;此过程,称为“协商缓存”验证和效验;同时,若存在no-cache,或Cache-Control: max-age=0;must-revalidate:true,没有缓存或无效,也需要做相应的“协商缓存”的“在服务端做验证和效验”处理 。
no-store:“不要做任何缓存”,任何响应的内容都不走缓存,无论是强制缓存、还是协商缓存。
private:默认,内容仅在UA客户端方可缓存,不能在代理服务器做缓存;
public:默认,内容即可缓存到UA客户端,也可缓存到cdn等其它任何代理服务器。3.2.2、服务端对浏览器“强制缓存”的资源设定并保留一个“过期”的副本copy,同时向浏览器的响应头写入一个“Cache-Control: max-age=***秒(为了兼容IE,若不使用缓存的情景:Cache-Control:no-cache 还附加了字段Pragma: no-cache )” 的过期字段 和 一个对缓存的唯一性“标记Etag(一般为base64格式的加密字符串等格式)”;浏览器在“缓存”时用同样的“标记Etag”来做本机存储和唯一性识别;
3.2.3、浏览器的“导航器”或“浏览器的内置js解释器引擎”,首次处理H5或Http请求的资源时:让本机代码向服务端发出xhr或fetch请求,同时将服务端的响应头的“标记Etag”和响应内容的结果,浏览器将响应消息同时写入本机“缓存”。
既然叫“协商”,就是:需要“浏览器执行前端代码”和“后端代码”,共同作协的结果,需要“前端开发人员”和“后端开发人员”,协商确定,共同一致的处理方法。
4、浏览器实现请求网络超大文件的本机存储的策略
4.1、针对非IndexDB的存储
首先,肯定是针对Disk Cache,无论是service worker,还是强制缓存或协商缓存;
其次,是请求的策略上,采用分块下载(chunked):浏览器客户端这一侧用“分片下载”来与服务端“协商请求”资源,而服务端则协商后采用将超大文件的资源,切割成N块(每块<=5MB的浏览器单个文件配额)的方式send发送响应给客户端,客户端存储到响应的Disk Cache,而读取或渲染时,以可读流的方式读取到内存,进行合并,当然此方式也受制于客户端“内存”的大小,还不是真正意义上的“超大文件”储存方案。
4.2、使用IndexedDB存储
使用IndexedDB技术,将不受制于单次请求单个文件的5MB配额的限制。理论上没有限制,IndexedDB官方并没有做特别的说明。大厂,一般采用此这种浏览器端的存储策略,比如我的博客:《大厂后台管理passportal的通行做法-之腾讯云研究》浏览器Disk Cache磁盘缓存及其协商缓存、及原生App和浏览器实现缓存的差异 中,腾讯云就使用了此存储方案。
4.3、使用H5原生的serviceWorker技术
(如上“2.2、Service Worker”节所述,略;其中也可以结合使用IndexedDB来进行存储)。
5、原生App和浏览器实现本机存储和缓存的差异
原生App和浏览器实现缓存的差异,首先要从本机存储的差异说起:
比较项 | 原生App | 浏览器 | 备注 |
本机存储的位置 | ◆电脑端:在目录访问权限框架内不限 | ◆浏览器自身的沙盒内的指定分类目录,分别存取不同的存储类型;并分别公开在浏览器devtool不同的分区 | 比如Android可参考:我的博文 |
◆移动端:总的,在“沙盒”内不限;细分,在沙盒内根据分类分子路径存取文件。 | |||
本机存储磁盘占用配额 | ◆均不限 | ◆单次请求中的单个文件:配额<=5M | |
本机存储的方法 | ◆完全取决于客户端的请求和服务端的响应,在内存和磁盘之间,相互转储 | ◆service worker:灵活,可自主决定哪些需要存储或缓存,以及方式等 | |
◆非service worker方式,取决于: | |||
◇ 浏览器自身的行为 | |||
◇ Memory Cache的存取特点 | |||
◇ Disk Cache的存取特点和存取的位置分类的关系 | |||
◇ Push Cachedeng background service的存取特点和存取位置分类的关系 |
然后,在它们各自的“本机存储”的基础上,对应其缓存的读写,即可,总的来说,就是从“内存”到“磁盘”之间的相互“转储”。细节,略。
喜欢的,就收藏并点个赞,鼓励我继续技术的原创写作及经验分享:
《大厂后台管理passportal鉴权登录的通行做法-之腾讯云研究》:
浏览器Disk Cache磁盘缓存及其协商缓存、及原生App和浏览器实现缓存的差异
今天的文章浏览器收藏夹在c盘什么位置_浏览器收藏夹在c盘什么位置分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/86508.html