10分钟彻底搞懂Http的强制缓存和协商缓存(小结)


Posted in Javascript onAugust 30, 2018

浏览器缓存

浏览器缓存是浏览器在本地磁盘对用户最近请求过的文档进行存储,当访问者再次访问同一页面时,浏览器就可以直接从本地磁盘加载文档。

所以根据上面的特点,浏览器缓存有下面的优点:

  • 减少冗余的数据传输
  • 减少服务器负担
  • 加快客户端加载网页的速度

浏览器缓存是Web性能优化的重要方式。那么浏览器缓存的过程究竟是怎么样的呢?

在浏览器第一次发起请求时,本地无缓存,向web服务器发送请求,服务器起端响应请求,浏览器端缓存。过程如下:

在第一次请求时,服务器会将页面最后修改时间通过Last-Modified标识由服务器发送给客户端,客户端记录修改时间;服务器还会生成一个Etag,并发送给客户端。

浏览器后续再次进行请求时:

浏览器缓存主要分为强强缓存(也称本地缓存)和协商缓存(也称弱缓存)。根据上图,浏览器在第一次请求发生后,再次发送请求时:

  • 浏览器请求某一资源时,会先获取该资源缓存的header信息,然后根据header中的Cache-Control和Expires来判断是否过期。若没过期则直接从缓存中获取资源信息,包括缓存的header的信息,所以此次请求不会与服务器进行通信。这里判断是否过期,则是强缓存相关。后面会讲Cache-Control和Expires相关。
  • 如果显示已过期,浏览器会向服务器端发送请求,这个请求会携带第一次请求返回的有关缓存的header字段信息,比如客户端会通过If-None-Match头将先前服务器端发送过来的Etag发送给服务器,服务会对比这个客户端发过来的Etag是否与服务器的相同,若相同,就将If-None-Match的值设为false,返回状态304,客户端继续使用本地缓存,不解析服务器端发回来的数据,若不相同就将If-None-Match的值设为true,返回状态为200,客户端重新机械服务器端返回的数据;客户端还会通过If-Modified-Since头将先前服务器端发过来的最后修改时间戳发送给服务器,服务器端通过这个时间戳判断客户端的页面是否是最新的,如果不是最新的,则返回最新的内容,如果是最新的,则返回304,客户端继续使用本地缓存。

一 强制缓存

强制缓存整体流程比较简单,就是在第一次访问服务器取到数据之后,在过期时间之内不会再去重复请求。实现这个流程的核心就是如何知道当前时间是否超过了过期时间。

强制缓存的过期时间通过第一次访问服务器时返回的响应头获取。在 http 1.0 和 http 1.1 版本中通过不同的响应头字段实现。

http 1.0

在 http 1.0 版本中,强制缓存通过 Expires 响应头来实现。 expires 表示未来资源会过期的时间。也就是说,当发起请求的时间超过了 expires 设定的时间,即表示资源缓存时间到期,会发送请求到服务器重新获取资源。而如果发起请求的时间在 expires 限定的时间之内,浏览器会直接读取本地缓存数据库中的信息(from memory or from disk),两种方式根据浏览器的策略随机获取。

http 1.1

在 http 1.1 版本中,强制缓存通过 Cache-Control 响应头来实现。Cache-Control 拥有多个值:

  • private:客户端可以缓存
  • public:客户端和代理服务器均可缓存;
  • max-age=xxx:缓存的资源将在 xxx 秒后过期;
  • no-cache:需要使用协商缓存来验证是否过期;
  • no-store:不可缓存

最常用的字段就是 max-age=xxx ,表示缓存的资源将在 xxx 秒后过期。一般来说,为了兼容,两个版本的强制缓存都会被实现。

总结

强制缓存只有首次请求才会跟服务器通信,读取缓存资源时不会发出任何请求,资源的 Status 状态码为 200,资源的 Size 为 from memory 或者 from disk ,http 1.1 版本的实现优先级会高于 http 1.0 版本的实现。

二 协商缓存

协商缓存与强制缓存的不同之处在于,协商缓存每次读取数据时都需要跟服务器通信,并且会增加缓存标识。在第一次请求服务器时,服务器会返回资源,并且返回一个资源的缓存标识,一起存到浏览器的缓存数据库。当第二次请求资源时,浏览器会首先将缓存标识发送给服务器,服务器拿到标识后判断标识是否匹配,如果不匹配,表示资源有更新,服务器会将新数据和新的缓存标识一起返回到浏览器;如果缓存标识匹配,表示资源没有更新,并且返回 304 状态码,浏览器就读取本地缓存服务器中的数据。

在 http 协议的 1.0 和 1.1 版本中也有不同的实现方式。

http 1.0

在 http 1.0 版本中,第一次请求资源时服务器通过 Last-Modified 来设置响应头的缓存标识,并且把资源最后修改的时间作为值填入,然后将资源返回给浏览器。在第二次请求时,浏览器会首先带上 If-Modified-Since 请求头去访问服务器,服务器会将 If-Modified-Since 中携带的时间与资源修改的时间匹配,如果时间不一致,服务器会返回新的资源,并且将 Last-Modified 值更新,作为响应头返回给浏览器。如果时间一致,表示资源没有更新,服务器返回 304 状态码,浏览器拿到响应状态码后从本地缓存数据库中读取缓存资源。

这种方式有一个弊端,就是当服务器中的资源增加了一个字符,后来又把这个字符删掉,本身资源文件并没有发生变化,但修改时间发生了变化。当下次请求过来时,服务器也会把这个本来没有变化的资源重新返回给浏览器。

http 1.1

在 http 1.1 版本中,服务器通过 Etag 来设置响应头缓存标识。Etag 的值由服务端生成。在第一次请求时,服务器会将资源和 Etag 一并返回给浏览器,浏览器将两者缓存到本地缓存数据库。在第二次请求时,浏览器会将 Etag 信息放到 If-None-Match 请求头去访问服务器,服务器收到请求后,会将服务器中的文件标识与浏览器发来的标识进行对比,如果不相同,服务器返回更新的资源和新的 Etag ,如果相同,服务器返回 304 状态码,浏览器读取缓存。

总结

协商缓存每次请求都会与服务器交互,第一次是拿数据和标识的过程,第二次开始,就是浏览器询问服务器资源是否有更新的过程。每次请求都会传输数据,如果命中缓存,则资源的 Status 状态码为 304 而不是 200 。同样的,一般来讲为了兼容,两个版本的协商缓存都会被实现,http 1.1 版本的实现优先级会高于 http 1.0 版本的实现。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Exitjs获取DataView中图片文件名
Nov 26 Javascript
jQuery验证Checkbox是否选中的代码 推荐
Sep 04 Javascript
Javascript base64编码实现代码
Dec 02 Javascript
js 实现在离开页面时提醒未保存的信息(减少用户重复操作)
Jan 16 Javascript
js常用自定义公共函数汇总
Jan 15 Javascript
js定时调用方法成功后并停止调用示例
Apr 08 Javascript
使用Javascript监控前端相关数据的代码
Oct 27 Javascript
AngularJS  ng-repeat遍历输出的用法
Jun 19 Javascript
Vue之mixin全局的用法详解
Aug 22 Javascript
vue filter 完美时间日期格式的代码
Aug 14 Javascript
vue组件命名和props命名代码详解
Sep 01 Javascript
详解webpack-dev-middleware 源码解读
Mar 23 Javascript
解决jQuery使用append添加的元素事件无效的问题
Aug 30 #jQuery
jsonp跨域及实现百度首页联想功能的方法
Aug 30 #Javascript
解决使用bootstrap的dropdown部件时报错:error:Bootstrap dropdown require Popper.js问题
Aug 30 #Javascript
解决vue的变量在settimeout内部效果失效的问题
Aug 30 #Javascript
JS+HTML5 Canvas实现简单的写字板功能示例
Aug 30 #Javascript
详解React native fetch遇到的坑
Aug 30 #Javascript
对Vue2 自定义全局指令Vue.directive和指令的生命周期介绍
Aug 30 #Javascript
You might like
php扩展ZF――Validate扩展
2008/01/10 PHP
php 编写安全的代码时容易犯的错误小结
2010/05/20 PHP
PHP中全面阻止SQL注入式攻击分析小结
2012/01/30 PHP
simplehtmldom Doc api帮助文档
2012/03/26 PHP
基于session_unset与session_destroy的区别详解
2013/06/03 PHP
php利用腾讯ip分享计划获取地理位置示例分享
2014/01/20 PHP
CodeIgniter中使用Smarty3基本配置
2015/06/29 PHP
Laravel基础-关于引入公共文件的两种方式
2019/10/18 PHP
js 自定义的联动下拉框
2010/02/07 Javascript
Jquery中国地图热点效果-鼠标经过弹出提示层信息的简单实例
2014/02/12 Javascript
js光标定位文本框回车表单提交问题的解决方法
2015/05/11 Javascript
基于JavaScript实现拖动滑块效果
2017/02/16 Javascript
微信小程序 下拉菜单简单实例
2017/04/13 Javascript
JavaScript中set与get方法用法示例
2018/08/15 Javascript
React 实现拖拽功能的示例代码
2019/01/06 Javascript
vue+element实现打印页面功能
2019/05/20 Javascript
nodejs中各种加密算法的实现详解
2019/07/11 NodeJs
pyv8学习python和javascript变量进行交互
2013/12/04 Python
python使用turtle库绘制树
2018/06/25 Python
python logging模块书写日志以及日志分割详解
2019/07/22 Python
Python字符串中添加、插入特定字符的方法
2019/09/10 Python
Pandas的Apply函数具体使用
2020/07/21 Python
谈谈python垃圾回收机制
2020/09/27 Python
Canvas在超级玛丽游戏中的应用详解
2021/02/06 HTML / CSS
中国跨境海淘网站:考拉海购
2016/08/01 全球购物
领先的钻石和订婚戒指零售商:Diamonds-USA
2016/12/11 全球购物
中国一家专注拼团的社交购物网站:拼多多
2018/06/13 全球购物
英国在线自行车店:Merlin Cycles
2018/08/20 全球购物
经销商培训邀请函
2014/01/21 职场文书
抗洪抢险事迹材料
2014/05/06 职场文书
美食节目策划方案
2014/05/31 职场文书
大学生学习面向未来的赶考思想汇报
2014/09/12 职场文书
标准演讲稿格式结尾应该怎么书写?
2019/07/17 职场文书
简单谈谈Python面向对象的相关知识
2021/06/28 Python
Python Django项目和应用的创建详解
2021/11/27 Python
python中的random模块和相关函数详解
2022/04/22 Python