浏览器缓存是什么?它的机制又是什么?

3次阅读

共计 4193 个字符,预计需要花费 11 分钟才能阅读完成。

对于浏览器缓存,相信很多开发者对它真的是又爱又恨。一方面极大地提升了用户体验,而另一方面有时会因为读取了缓存而展示了“错误”的东西,而在开发过程中千方百计地想把缓存禁掉。那么浏览器缓存究竟是个什么样的神奇玩意呢?
什么是浏览器缓存:
简单来说,浏览器缓存就是把一个已经请求过的 Web 资源(如 html 页面,图片,js,数据等)拷贝一份副本储存在浏览器中。缓存会根据进来的请求保存输出内容的副本。当下一个请求来到的时候,如果是相同的 URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,还是向源服务器再次发送请求。比较常见的就是浏览器会缓存访问过网站的网页,当再次访问这个 URL 地址的时候,如果网页没有更新,就不会再次下载网页,而是直接使用本地缓存的网页。只有当网站明确标识资源已经更新,浏览器才会再次下载网页。

比如说,在页面请求之后,web 资源都被缓存了,在后面的重复请求中,许多资源都是直接从缓存中读取的(from cache),而不是重新去向服务器请求。
为什么使用缓存:
(1)减少网络带宽消耗
无论对于网站运营者或者用户,带宽都代表着金钱,过多的带宽消耗,只会便宜了网络运营商。当 Web 缓存副本被使用时,只会产生极小的网络流量,可以有效的降低运营成本。
(2)降低服务器压力
给网络资源设定有效期之后,用户可以重复使用本地的缓存,减少对源服务器的请求,间接降低服务器的压力。同时,搜索引擎的爬虫机器人也能根据过期机制降低爬取的频率,也能有效降低服务器的压力。
(3)减少网络延迟,加快页面打开速度
带宽对于个人网站运营者来说是十分重要,而对于大型的互联网公司来说,可能有时因为钱多而真的不在乎。那 Web 缓存还有作用吗?答案是肯定的,对于最终用户,缓存的使用能够明显加快页面打开速度,达到更好的体验。
浏览器端的缓存规则:
对于浏览器端的缓存来讲,这些规则是在 HTTP 协议头和 HTML 页面的 Meta 标签中定义的。他们分别从新鲜度和校验值两个维度来规定浏览器是否可以直接使用缓存中的副本,还是需要去源服务器获取更新的版本。
新鲜度(过期机制):也就是缓存副本有效期。一个缓存副本必须满足以下条件,浏览器会认为它是有效的,足够新的:
1. 含有完整的过期时间控制头信息(HTTP 协议报头),并且仍在有效期内;
2. 浏览器已经使用过这个缓存副本,并且在一个会话中已经检查过新鲜度;
满足以上两个情况的一种,浏览器会直接从缓存中获取副本并渲染。
校验值(验证机制):服务器返回资源的时候有时在控制头信息带上这个资源的实体标签 Etag(Entity Tag),它可以用来作为浏览器再次请求过程的校验标识。如过发现校验标识不匹配,说明资源已经被修改或过期,浏览器需求重新获取资源内容。
浏览器缓存的控制:
(1)使用 HTML Meta 标签
Web 开发者可以在 HTML 页面的 <head> 节点中加入 <meta> 标签,代码如下
<meta http-equiv=”Pragma” content=”no-cache”>
<!- Pragma 是 http1.0 版本中给客户端设定缓存方式之一,具体作用会在后面详细介绍 –>
上述代码的作用是告诉浏览器当前页面不被缓存,每次访问都需要去服务器拉取。但是!这里有个坑 …
事实上这种禁用缓存的形式用处很有限:
a. 仅有 IE 才能识别这段 meta 标签含义,其它主流浏览器仅识别“Cache-Control: no-store”的 meta 标签。
b. 在 IE 中识别到该 meta 标签含义,并不一定会在请求字段加上 Pragma,但的确会让当前页面每次都发新请求(仅限页面,页面上的资源则不受影响)。
(2)使用缓存有关的 HTTP 消息报头
在这里就需要先跟大家介绍一下 HTTP 的相关知识。一个 URI 的完整 HTTP 协议交互过程是由 HTTP 请求和 HTTP 响应组成的。有关 HTTP 详细内容可参考《Hypertext Transfer Protocol — HTTP/1.1》、《HTTP 协议详解》等。
在 HTTP 请求和响应的消息报头中,常见的与缓存有关的消息报头有:

  在我们对 HTTP 请求头和响应头的部分字段有了一定的认识之后,我们接下来就来讨论不同字段之间的关系和区别:
· Cache-Control 与 Expires
Cache-Control 与 Expires 的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。只不过 Cache-Control 的选择更多,设置更细致,如果同时设置的话,其优先级高于 Expires。
· Last-Modified/ETag 与 Cache-Control/Expires
配置 Last-Modified/ETag 的情况下,浏览器再次访问统一 URI 的资源,还是会发送请求到服务器询问文件是否已经修改,如果没有,服务器会只发送一个 304 回给浏览器,告诉浏览器直接从自己本地的缓存取数据;如果修改过那就整个数据重新发给浏览器;
Cache-Control/Expires 则不同,如果检测到本地的缓存还是有效的时间范围内,浏览器直接使用本地副本,不会发送任何请求。两者一起使用时,Cache-Control/Expires 的优先级要高于 Last-Modified/ETag。即当本地副本根据 Cache-Control/Expires 发现还在有效期内时,则不会再次发送请求去服务器询问修改时间(Last-Modified)或实体标识(Etag)了。
一般情况下,使用 Cache-Control/Expires 会配合 Last-Modified/ETag 一起使用,因为即使服务器设置缓存时间, 当用户点击“刷新”按钮时,浏览器会忽略缓存继续向服务器发送请求,这时 Last-Modified/ETag 将能够很好利用 304,从而减少响应开销。
  · Last-Modified 与 ETag
你可能会觉得使用 Last-Modified 已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要 Etag(实体标识)呢?HTTP1.1 中 Etag 的出现主要是为了解决几个 Last-Modified 比较难解决的问题:

Last-Modified 标注的最后修改只能精确到秒级,如果某些文件在 1 秒钟以内,被修改多次的话,它将不能准确标注文件的新鲜度
如果某些文件会被定期生成,当有时内容并没有任何变化,但 Last-Modified 却改变了,导致文件没法使用缓存
有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形

Etag 是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-Modified 与 ETag 是可以一起使用的,服务器会优先验证 ETag,一致的情况下,才会继续比对 Last-Modified,最后才决定是否返回 304。Etag 的服务器生成规则和强弱 Etag 的相关内容可以参考,《互动百科 -Etag》和《HTTP Header definition》,这里不再深入。
注意:
1. Etag 是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存,但是需要注意的是分布式系统里多台机器间文件的 last-modified 必须保持一致,以免负载均衡到不同机器导致比对失败,Yahoo 建议分布式系统尽量关闭掉 Etag(每台机器生成的 etag 都会不一样,因为除了 last-modified、inode 也很难保持一致)。
  2. Last-Modified/If-Modified-Since 要配合 Cache-Control 使用,Etag/If-None-Match 也要配合 Cache-Control 使用。
浏览器 HTTP 请求流程:
第一次请求:

再次请求:

用户行为与缓存:
  浏览器缓存行为还有用户的行为有关,具体情况如下:

如果想学习 Java 工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty 源码分析的朋友可以加 Java 进阶交流群:895244712,有阿里大牛直播讲解技术,以及 Java 大型互联网技术的视频免费分享给大家。
不能缓存的请求:
当然并不是所有请求都能被缓存,无法被浏览器缓存的请求如下:
1. HTTP 信息头中包含 Cache-Control:no-cache,pragma:no-cache(HTTP1.0),或 Cache-Control:max-age= 0 等告诉浏览器不用缓存的请求
2. 需要根据 Cookie,认证信息等决定输入内容的动态请求是不能被缓存的
3. 经过 HTTPS 安全加密的请求(有人也经过测试发现,ie 其实在头部加入 Cache-Control:max-age 信息,firefox 在头部加入 Cache-Control:Public 之后,能够对 HTTPS 的资源进行缓存,参考《HTTPS 的七个误解》)
4. POST 请求无法被缓存
5. HTTP 响应头中不包含 Last-Modified/Etag,也不包含 Cache-Control/Expires 的请求无法被缓存
参考资料:
1. http://www.cnblogs.com/520yang/articles/4807408.html  浏览器 HTTP 协议缓存机制详解 [](http://www.cnblogs.com/520yan…
2. https://my.oschina.net/leejun2005/blog/369148  浏览器 HTTP 协议缓存机制详解
3. http://web.jobbole.com/82997/  浏览器缓存机制浅析
4. http://www.alloyteam.com/2012/03/web-cache-2-browser-cache/  Web 浏览器的缓存机制 
5. http://www.cnblogs.com/vajoy/p/5341664.html  浅谈浏览器 http 的缓存机制
6. http://mp.weixin.qq.com/s/yf0pWRFM7v9Ru3D9_JhGPQ  浏览器缓存机制剖析

正文完
 0