Web缓存机制之http缓存
啥是缓存?
当从客户端向服务端获取资源,需要建立链接,资源传输等一系列消耗,为了方便下次获取的资源更快,性能开销更小,是不是可以把第一次获取的资源储存起来,下次直接拿呢,没错这就是缓存。
存哪了?
好了知道什么是缓存了,那么缓存具体存哪了?
Service Worker
W3C 组织早在 2014 年 5 月就提出过 Service Worker 这样的一个 HTML5 API ,主要用来做持久的离线缓存。service worker是浏览器的一个高级特性,本质是一个web worker,是独立于网页运行的脚本。 web worker这个api被造出来时,就是为了解放主线程。
Memory Cache
内存缓存,常见于强缓存
Disk Cache
磁盘缓存,常见于强缓存
缓存类型有哪些?
强缓存
浏览器强制缓存服务端提供的资源。
在web应用中,时常可以status code: 200(from memory cache)或者status code: 200(from disk cache),没错这就是强缓存的实际应用。那么这时候聪明的你一定思考过,这两种方式有什么区别呢?
memory cache实际上disk cache 快的多。如果从远程 web 服务器直接提取访问文件可能500毫秒,那么磁盘访问可能需要10-20毫秒,而内存访问只需要100纳秒
那么问题又来了,如果我们如何控制是从memory还是从disk缓存获取呢。
看个栗子
第一次获取资源之后,再次获取从缓存中获取资源(memory cache)刷新同样。
关闭浏览器从新打开,观察该资源获取方式,从memory cache变成了disk cache
这里原因是什么?答案就是浏览器来决定使用哪种方式获取资源。这里引发了两外一个问题,浏览器缓存原理。
浏览器缓存原理
获取资源首先从memory中获取如果有直接加载目标资源。
如果memory没有,选择从disk获取,如果有直接加载
如果disk也没有,那么就进行网络请求
加载到的资源缓存到硬盘和内存
所以加载优先级就是memory cache大于disk cache,毕竟内存更快嘛~
流程图:
协商缓存
协商缓存,是在缓存过期的情况下,客户端和服务端协商,确认客户端缓存是否需要更新。
- 使用资源最后修改的日期来判断(http1.0)
- 使用令牌(ETag)标识来识别(http1.1)
强缓存协商缓存优先级
同时设置了强缓存跟协商缓存,那么优先级是什么呢?
首先下结论:强缓存优先级大于协商缓存
回顾协商缓存,是在缓存过期的情况下,客户端和服务端协商,确认客户端缓存是否需要更新。这个缓存过期指定就是强缓存。通常在系统使用缓存机制的时候,我们在强缓存或者协商缓存之间选择其中一种。
看个栗子
一个status code是304的请求
响应的时候多个一个Etag标签作为令牌
服务器If-None-Match来与Etag做对比
好了到这里协商缓存是不是已经了解了呢~
那么如何在实践中设置缓存类型呢~
Cache-Control(http1.1版本)
- no-store
- no-cache
- max-age=x
- s-maxage=x
- public
- private
- must-revalidate
no-store
禁止使用缓存。带有no-store的响应不会被缓存到任意的磁盘或者内存里。p.s.通常没有这么用的。
no-cache
协商缓存使用场景
协商缓存使用场景
no-cache等同于max-age=0
告诉浏览器、缓存服务器,不管本地副本是否过期,使用资源副本前,一定要到源服务器进行副本有效性校验。校验有效性?没错通常这么设置是为了使用协商缓存。
http:1.1
请求头: If-None-Match
响应头: Etag
http:1.0
请求头: If-Modified-since:Date
响应头: Last-Modified:Date
max-age=x
强缓存使用场景(max-age=0除外)
缓存内容将在x秒后失效
s-maxage=x
考虑到max-age适用于所有缓存,而s-maxage仅适用于共享缓存(代理、网关缓存、CDN等等)
public/private
private
您不允许代理缓存通过它们传播的数据。 最后,这一切归结为您发送的页面/文件中包含的数据。
例如,您的ISP可能在您和Internet之间有一个不可见的代理,即缓存网页以减少所需的带宽量并降低成本。 通过使用cache-control:private,您指定它不应该缓存页面(但允许最终用户这样做)
public
使用cache-control:public,则表示每个人都可以缓存该页面,因此代理将保留一个副本。
总结:如果每个人都可以访问(例如,此页面中的徽标)缓存控制:public可能会更好,因为更多的人缓存它,您需要的带宽越少。 如果它是与所连接的用户相关的(例如,此页面中的HTML包含我的用户名,所以对其他人来说并不有用)cache-control:private将会更好,因为代理将缓存数据这不会被其他用户请求,并且他们也可能会保留不想保存在不信任的服务器中的数据。
must-revalidate
告诉浏览器、缓存服务器,本地副本过期前,可以使用本地副本;本地副本一旦过期,必须去源服务器进行有效性校验。must-revalidate生效的场景还有一个大前提,
那就是 HTTP 规范是允许客户端在某些特殊情况下直接使用过期缓存的。
后续会补充所有与http请求相关的知识点,如果哪里阐述或者理解不对希望指正,共同进步~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构