前言

在浏览器众多缓存中的HTTP缓存可能很多人对这个的概念并没有很清晰,每个人都知道进入一次网页之后再刷新一次页面,加载速度会比首次加载快非常多,每个人都知道这是浏览器缓存的magic,但是对此背后的原因可能不甚了解...


当我们在谈论HTTP缓存时我们在谈论什么:

我们实际上是在谈论下面这两种情况:

如上图,浏览器对静态资源的HTTP缓存有两种情况,一种是强缓存(本地缓存),另一种是弱缓存(协商缓存)。


缓存流程:

浏览器第一次请求资源时:

浏览器第一次请求资源时,必须下载所有的资源,然后根据响应的header内容来决定,如何缓存资源。可能采用的是强缓存,也可能是弱缓存

浏览器后续请求资源时的匹配流程:

由上图可以知道当浏览器请求一个静态资源时的HTTP流程:

  1. 强缓存阶段:先在本地查找该资源,如果发现该资源,并且其他限制也没有问题(比如:缓存有效时间),就命中强缓存,返回200,直接使用强缓存,并且不会发送请求到服务器
  2. 弱缓存阶段:在本地缓存中找到该资源,发送一个http请求到服务器,服务器判断这个资源没有被改动过,则返回304,让浏览器使用该资源。
  3. 缓存失败阶段(重新请求):当服务器发现该资源被修改过,或者在本地没有找到该缓存资源,服务器则返回该资源的数据。

强缓存与弱缓存的区别:

获取资源形式: 都是从缓存中获取资源的。

状态码: 强缓存返回200(from cache),弱缓存返回304状态码

请求(最大区别):

强缓存不发送请求,直接从缓存中取。

弱缓存需要发送一个请求,验证这个文件是否可以使用(有没有被改动过)。


强缓存:

强缓存是利用Expires或者Cache-Control,让原始服务器为文件设置一个过期时间,在多长时间内可以将这些内容视为最新的。

若时间未过期,则命中强缓存,使用缓存文件不发送请求。

Cache-Control

Cache-Control 是http1.1中为了弥补Expires的缺陷而加入的,当Expires和Cache-Control同时存在时,Cache-Control优先级高于Expires。

选项:

可缓存性:

public: 表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存。

private: 只有用户自己的浏览器能够进行缓存,公共的代理服务器不允许缓存。

no-cache: 强制浏览器在使用cache拷贝之前先提交一个http请求到源服务器进行确认。http请求没有减少,会减少一个响应体(文件内容),这种个选项类似弱缓存。

only-if-cached: 表明客户端只接受已缓存的响应,并且不要向原始服务器检查是否有更新的拷贝。

到期设置:

max-age=60:设置缓存存储的最大周期,超过这个时间缓存被认为过期(单位秒)。 这里是60秒

其他设置:

no-store: 告诉浏览器在任何情况下都不要进行cache,不在本地保留拷贝。

must-revalidate: 缓存必须在使用之前验证旧资源的状态,并且不可使用过期资源。

更多设置,移动MDN

// 示例 Cache-Control: no-cache, no-store, must-revalidate Cache-Control:public, max-age=31536000 Cache-Control: max-age=3600, must-revalidate

http1.0时代的缓存 Expires+Pragma

Expires用于设置缓存到期时间:

指定缓存到期GMT的绝对时间,如果设了max-age,max-age就会覆盖expires,如果expires到期需要重新请求。

Expires:Sat, 09 Jun 2018 08:13:56 GMT

有一个问题是由于使用具体时间,如果时间表示出错或者没有转换到正确的时区都可能造成缓存生命周期出错。

Pragma禁用缓存:

Pragma : no-cache 表示防止客户端缓存,需要强制从服务器获取最新的数据;

Pragma : no-cache //只有这一个用法 禁用缓存,强制从服务器获取最新的数据;

强缓存命中 from memory cache & from disk cache

在测试的时候,看到命中强缓存时,有两种状态,200 (from memory cache) cache & 200 (from disk cache),于是去找了一下这两者的区别:

memory cache: 将资源存到内存中,从内存中获取。

disk cache:将资源缓存到磁盘中,从磁盘中获取。

二者最大的区别在于:当退出进程时,内存中的数据会被清空,而磁盘的数据不会。

更详细的介绍推荐这篇文章


弱缓存:

如果强缓存时间过期,或者没有设置,导致未命中的话。就进入到了弱缓存的阶段了,

Last-Modified & if-modified-since:

Last-Modified与If-Modified-Since是一对报文头,属于http 1.0。

last-modified是web服务器认为文件的最后修改时间,last-modified是第一次请求文件的时候,服务器返回的一个属性。

Last-Modified: Sat, 09 Jun 2018 08:13:56 GMT

第二次请求这个文件时,浏览器把If-Modified-Since发送给服务器,询问该时间之后文件是否被修改过。

If-Modified-Since: Sat, 09 Jun 2018 08:13:56 GMT // 跟Last-Modified的值一样

ETag & If-None-Match

ETag与If-None-Match是一对报文,属于http 1.1。

ETag是一个文件的唯一标志符。就像一个哈希或者指纹,每个文件都有一个单独的标志,只要这个文件发生了改变,这个标志就会发生变化。

ETag机制类似于乐观锁机制,如果请求报文的ETag与服务器的不一致,则表示该资源已经被修改过来,需要发最新的内容给浏览器。

ETag也是首次请求的时候,服务器返回的:

ETag: "8F759D4F67D66A7244638AD249675BE2" // 长这样

If-None-Match也是浏览器发送到服务器验证,文件是否改变的:

If-None-Match: "8F759D4F67D66A7244638AD249675BE2" // 跟ETag的值一样

Etag/lastModified过程如下:

  1. 客户端第一次向服务器发起请求,服务器将附加Last-Modified/ETag到所提供的资源上去
  2. 当再一次请求资源,如果没有命中强缓存,在执行在验证时,将上次请求时服务器返回的Last-Modified/ETag一起传递给服务器。
  3. 服务器检查该Last-Modified或ETag,并判断出该资源页面自上次客户端请求之后还未被修改,返回响应304和一个空的响应体。

同时使用两个报文头:

同时使用这两个报文头,两个都匹配才会命中弱缓存,否则将重新请求资源。

Etag 主要为了解决 Last-Modified 无法解决的一些问题:

  1. 一些文件也许内容并不改变(仅仅改变的修改时间),这个时候我们不希望文件重新加载。(Etag值会触发缓存,Last-Modified不会触发)
  2. If-Modified-Since能检查到的粒度是秒级的,当修改非常频繁时,Last-Modified会触发缓存,而Etag的值不会触发,重新加载。
  3. 某些服务器不能精确的得到文件的最后修改时间。·

用户操作行为与缓存

F5刷新导致强缓存失效。

ctrl+F5强制刷新页面强缓存,弱缓存都会失效。

如何设置?

一般是服务器端设置这些请求头的,我自己试了用阿里云服务器设置Cache-Control,设置一下很方便的。

嗯,据说客户端也是可以设置强弱缓存,但是找了半天不知道怎么设置,如果有路过的大佬知道,可以指导一波^_^。

没有设置强缓存,返回200

如下图这种情况,就不太懂怎么回事,下方的解释也没看明白,图片内容出自这篇文章

结语

通过网络重复请求资源既缓慢,成本又高,缓存和重用以前获取的资源的能力成为优化性能很关键的一个方面,也是大厂面试时很频繁出现的内容,掌握好这块知识点是非常重要的,希望本文能给你带来些收获。

当我们在谈论HTTP缓存时我们在谈论什么相关推荐

  1. 新书上市 | 当我们在谈论贝叶斯时我们在谈论什么:用贝叶斯的眼光看世界

    #新书推荐# 你跟朋友逛购物中心,时至中午,你们打算吃点东西.面对众多餐馆,你们会怎么办? 也许你们真的一无所知,随便挑了一家餐馆,但毕竟世上没多少"一无所知"的事.如果你朋友吃不 ...

  2. 如何防止android app被误删除,如何避免手机清理缓存时误删了重要文件【注意事项】...

    如何避免手机清理缓存时误删了重要文件? 缓存只是内存中少部分数据的复制品,所以CPU到缓存中寻找数据时,也会出现找不到的情况(因为这些数据没有从内存复制到缓存中去),这时CPU还是会到内存中去找数据, ...

  3. 当谈论设备指纹时,我们到底在说什么?(转)

    原标题:当谈论设备指纹时,我们到底在说什么? http://finance.ifeng.com/a/20170829/15621402_0.shtml 中新网8月29日电  "设备" ...

  4. 谈论源码_当我们谈论软件“替代品”时,这是什么意思?

    谈论源码 " 替代 "一词是那些易变的术语之一,其定义随视角而变化. 例如,一个人的替代品就是另一个人的规范. 通常,"替代"一词被认为是由以下事实定义的:它不 ...

  5. 谈谈使用Redis缓存时批量删除的几种实现

    谈谈使用Redis缓存时批量删除的几种实现 原文:谈谈使用Redis缓存时批量删除的几种实现 前言 在使用缓存的时候,我们时不时会遇到这样一个需求,根据缓存键的规则去批量删除这些数据,比较常见的就是按 ...

  6. Dreamweaver8加载站点缓存时卡死,解决办法:

    Dreamweaver8加载站点缓存时卡死,解决办法: 无论中文版的 dreamweaver 8,还是英文版本的dw8或绿色版本的DW8,都可能出现无法启动的情况,这个bug的出现是因为先前你曾经在使 ...

  7. npm强制清除缓存时无法清除问题

    npm强制清除缓存时无法清除问题 使用webpack时遇到的问题,npm强制清除缓存时无法清除. 强制清除npm指令 npm cache clean -f 在执行以上指令后,命令一直没有终止,具体忘了 ...

  8. 使用缓存时对于加锁的思考(* * * * *)

    使用缓存时对于加锁的思考 原文:https://www.cnblogs.com/rongdi/p/9034886.html 突然发现之前写的自己实现XXX的话题不是很被大众关注,可能是真的写的不行,也 ...

  9. 谈论源码_当我们谈论开放音乐时,我们指的是什么?

    谈论源码 了解Bolero最近进入公共领域后,使我想到了"开放音乐"的总体概念. 在哪里找到的? 什么特征定义开放音乐? 因此,我让最喜欢的搜索引擎帮助我完成了侦探工作,以期发现对 ...

最新文章

  1. uv_timer_t的释放问题
  2. CentOS7编译安装MySQL5.7之后安装mysql-devel出错解决方案
  3. 模版方法模式/Template Method
  4. python工作太难找-Python工作难找吗?
  5. 转:深度学习与自然语言处理之五:从RNN到LSTM
  6. 树莓派各版本配置对比
  7. Django请求响应对象
  8. JDBC学习笔记(7)——事务的隔离级别批量处理
  9. 响应在此上下文中不可用
  10. 客户和顾客是一个意思吗_“啤酒度数”和“啤酒酒精度”一个意思吗?
  11. NetStatusEvent info对象的状态或错误情况的属性
  12. 参与社团活动的意义_大学参加社团活动有意义吗?
  13. (转) QImage总结
  14. java编译器哪个好_java编译器什么好?java编译器工作原理是什么?
  15. Java基础入门笔记
  16. QQ聊天记录恢复、迁移教程(改变默认存储位置、个人文件夹保存位置)【转载】
  17. translation exercise 3
  18. 【转】凡事事必躬亲 是一种恶习
  19. centos浏览器可以上外网但是ping不通
  20. 你也能看懂的:灰色预测算法

热门文章

  1. vba移动文件_Excel VBA之FSO-2.3文件夹的移动
  2. Linux基础优化方法(二)———系统安全相关优化:防火墙和selinux
  3. oracle %date 0 10%,“date:~0,10%“是什么意思?
  4. 多维数组的索引与切片_Numpy库使用入门(二)数据的索引和切片
  5. JFreeChart基本的用法实例(一)
  6. led显示屏服务器怎么设置,led显示屏怎么改字幕 led显示屏改字幕方法
  7. 5 table滑动固定_内滑动钢套钢蒸汽直埋保温钢管
  8. 安卓机高的地图要用浏览器打开_浏览器F12操作概述
  9. 对linux做一个简单介绍,对“Fork”做一个技术方面的简介
  10. c语言程序设保安值班,保安值班系统