协商缓存

所谓“协商”,可以理解为:客户端和服务端双方商量着来

客户端检查资源超过有效期、强缓存命中失败的情况下,则发出请求“询问”服务器是否资源真的过期了,询问的同时在请求头要携带着资源的「上次更新时间」或者「唯一实体标识」(不同http版本导致的共存问题)。

服务端核对客户端要请求的资源的「上次更新时间」或者「唯一实体标识」:

  • 若一致,说明命中协商缓存,只返回304;
  • 若不一致,说明资源有更新,则返回200、新资源,同时响应头返回「资源修改时间」后者「资源最新的实体标识」。同时,客户端拿到新的资源及其修改时间与标识后,重新进行缓存。

概括如下图:

缓存验证

协商缓存就是缓存验证。

触发时机:

  • 用户点击刷新按钮时会开始缓存验证。
  • 如果缓存的响应头信息里含有"Cache-control: must-revalidate”的定义,在浏览的过程中也会触发缓存验证。
  • 另外,在浏览器偏好设置里设置Advanced->Cache为强制验证缓存也能达到相同的效果。

触发条件:

只有在服务器返回强校验器或者弱校验器时才会进行验证。

附带条件请求

形如 If-xxx 这种样式的请求首部字段,都可称为条件请求。

服务器接 收到附带条件的请求后,只有判断指定条件为真时,才会执行请求。

协商缓存中,就有很多这样的附带条件请求。

《图解HTTP》

协商缓存 特点:

  • 服务端校验
  • 304 Not Modified状态码
  • Last-Modified
  • Etag

304(Not Modified)

该状态码虽然是3XX的类别,但是跟301、302不一样,不是重定向的含义。

304,Not Modified。表示服务端资源未改变,可直接使用客户端缓存过的、未过期的资源。

他的触发条件是:

1、客户端采用GET方法,且在请求报文中含有“If-Match”、“If-Modified-Since”、“If-None-Match”、“If-Range”、“If-Unmodified-Since”等字段

2、服务器端接收到请求,允许请求并访问资源。但因客户端的请求未满足条件,就直接返回了304。

304状态码返回时,不包含任何响应的主体部分。

也就是说,如果命中协商缓存,服务端响应请求时,只会返回一个304状态码、并没有实际上的文件内容,因此在响应体体积上的节省是协商缓存的优化点

HTTP/1.0 Last-Modified组

Last-Modified (资源的最后修改日期时间)

实体首部字段:Last-Modified,表示资源最后被修改的时间

格式如:

last-modified: Thu, 01 Jan 1970 00:00:00 GMT

这句话就像是服务器告诉客户端,你请求的这个文件是1970年1月1日修改的。

Last-Modified是一种缓存弱校验器。说它弱是因为它只能精确到一秒。

如果响应头里含有这个信息,客户端可以在后续的请求中带上 If-Modified-Since 来验证缓存:

If-Modified-Since (比较资源的更新时间)

请求首部字段

他是与Last-Modified对应的字段,存储的是上次缓存的资源最终更新时间,也就是上次缓存资源时获取的Last-Modified的值。

用于确认代理服务器/客户端拥有的本地资源的有效性

如果在If-Modified-Since字段指定的日期时间后,资源发生了改变,服务器会接受请求。

上图中,服务端拿着他的值和服务端本地被请求资源的Last-Modified进行比较:

  • 如果Last-Modified <= If-Modified-Since,说明资源一致,命中协商缓存,返回304状态码 Not Modified即可。
  • 如果Last-Modified > If-Modified-Since,说明资源被修改,需要返回最新资源给客户端。

他的格式如:

if-modified-since: Thu, 01 Jan 1970 00:00:00 GMT

HTTP/1.1 Etag组

Etag (资源的匹配信息)

响应首部字段,缓存的一种强校验器

实体标记(Etag)是与特定资源关联的特定值,是资源唯一性标识的字符串。服务器会为每份资源分配对应的 ETag 值。 并通过响应头首部字段告知客户端资源的实体标识。

格式如:

etag: f7b80870fbcd8f9da18ab22d2ef1932c

特点:

  • 当资源更新时,ETag 值也需要更新。
  • 而且,生成 ETag 值时,并没有统一的算法规则,而仅仅是由服务器来分配。所以分布式服务器系统,一模一样的一个文件的Etag值可能不一样。
  • 此外,因为是按照内容不同来生成的唯一标识,中英文对应版本的资源,虽然地址相同,其Etag不同。

强弱Etag:

ETag 中有强 ETag 值和弱 ETag 值之分。

强ETag值

强 ETag 值,不论实体发生多么细微的变化都会改变其值。

ETag: "usagi-1234"

弱ETag值

弱 ETag 值只用于提示资源是否相同。只有资源发生了根本改变,产 生差异时才会改变 ETag 值。

这时,会在字段值最开始处附加 “W/”。如下:

ETag: W/"usagi-1234" 

If-None-Match (比较实体标记)

请求首部字段

他是与Etag对应的字段,存储的是上次缓存的资源的实体标记值,也就是上次缓存资源时获取的Etag的值。

协商缓存时,客户端携带该字段与服务端资源的Etag字段值进行比对,只有在If-None-Match的字段值与Etag值匹配不上、不一致时,命中协商缓存

GET或HEAD请求方法中,使用If-None-Match可获取最新的资源。

格式如:

if-none-match: f7b80870fbcd8f9da18ab22d2ef1932c

他和If-Match的作用相反。

If-Match 与412 状态码

用法和规则基本同If-None-Match,但判断逻辑完全相反。

If-Match的这个条件的判断逻辑是:只有当 If-Match 的字段值跟 ETag 值匹配一致时才会命中协商缓存。服务器才会接受请求 并返回200和新数据。

反之,服务器返回状态码 412 Precondition Failed 的响应。

还可以使用 星号(*) 指定 If-Match 的字段值。

针对这种情况,服务器将会忽略 ETag 的值,只要资源存在就处理请求。

if-match: f7b80870fbcd8f9da18ab22d2ef1932c

或者

if-match: *

对比

首先,Etag的优先级高于Last-Modified。

Last-Modified和Etag的优缺点分析如下:

Last-Modified优点

不存在版本问题,每次请求都会去服务器进行校验。服务器对比最后修改的时间,如果相同返回 304,不同的话返回 200 以及相应的数据资源

Last-Modified缺点

  1. 只要资源修改,无论内容是否发生实质性的变化,都会将该资源返回给客户端。 例如周期性重写,这种情况下该资源包含的数据实际上是一样的;
  2. 以时刻作为标识,无法识别一秒内进行多次修改的情况。如果资源更新的速度是秒以下单位,那么该缓存是不能被使用的,因为它的时间单位最低是秒;
  3. 某些服务器不能精确的得到文件最后修改时间; 如果文件是通过服务器动态生成的,那么该方法的更新时间永远是生成的时间,尽管文件可能没有变化,所以起不到缓存的作用

Etag优点

  • 可以更加精确的判断资源是否被修改,
  • 可以识别一秒内多次修改的情况;
  • 不存在版本问题,每次请求时都会去服务器进行校验。

Etag缺点

  • 计算 Etag 值需要性能损耗;
  • 分布式服务器时依赖算法:分布式服务器存储的情况下,计算 Etag 的算法如果不一样,会导致浏览器从一台服务器上获得页面内容后到另外一台服务器上进行验证时现 Etag 不匹配的情况。

两组字段流程整理如下

最后再整体回顾、复习一下子。

(注意:实际HTTP1.1的请求中,两组字段同时包含在请求及响应头中,我这里为了加深组CP的印象,分开阐述)

1、Last-Modified组整体流程如下:

  • 服务器通过 Last-Modified 字段告知客户端,资源最后一次被修改的时间
  • 浏览器将这个值和内容一起记录在缓存数据库中
  • 下一次请求相同资源的时候,浏览器从自己的缓存中找出"不确定是否过期的"缓存。因此在请求头中将上次的 Last-Modified 的值写入到请求头的 If-Modified-since 字段
  • 服务器会将 If-Modified-since 的值与 If-Modified 字段进行对比。如果相等,则表示未修改,响应 304;反之,表示修改响应 200 状态码并返回数据

2、Etag组整体流程如下:

浏览器在发起请求时,服务器在响应头中返回请求资源的唯一标识。在下一次请求时,会将上一次返回的 Etag 值赋值给 If-None-match 并添加在响应头中。服务器将浏览器传来的 if-no-matched 跟自己的本地的资源的 Etag 做对比,如果匹配,则返回 304 通知浏览器读取本地缓存,否则返回 200 和更新后的资源。


HTTP缓存——协商缓存(缓存验证)的更多相关文章

  1. http协商缓存VS强缓存

    之前一直对浏览器缓存只能描述一个大概,深层次的原理不能描述上来:终于在前端的两次面试过程中被问倒下,为了泄恨,查阅一些资料最终对其有了一个更深入的理解,废话不多说,赶紧来看看浏览器缓存的那些事吧,有不 ...

  2. 浏览器缓存_HTTP强缓存和协商缓存

    浏览器缓存 浏览器缓存是浏览器在本地磁盘对用户最近请求过的文档进行存储,当访问者再次访问同一页面时,浏览器就可以直接从本地磁盘加载文档. 所以根据上面的特点,浏览器缓存有下面的优点: 减少冗余的数据传 ...

  3. 浏览器相关,关于强缓存、协商缓存、CDN缓存。

    强缓存和协商缓存 在介绍缓存的时候,我们习惯将缓存分为强缓存和协商缓存两种.两者的主要区别是使用本地缓存的时候,是否需要向服务器验证本地缓存是否依旧有效. 顾名思义,协商缓存,就是需要和服务器进行协商 ...

  4. web缓存之--http缓存机制

    一.web缓存可以分为数据库缓存.代理服务器缓存.浏览器缓存. 其中浏览器缓存又包含很多内容:http缓存.indexDb.cookie.localStorage等.本片只讨论http缓存相关内容. ...

  5. http缓存与离线缓存

    一.http协议实现缓存 1. 缓存头部 通用缓存.条件缓存.缓存控制三大类 头部名称 说明 请求/响应 通用缓存头部 控制客户端是否向服务器发送请求或者是服务端响应请求   cache-contro ...

  6. 【HTTP缓存】浏览器缓存理论知识

    时间:2016-12-12 17:51:30 作者: zhongxia 零.前言 这里主要写的是理论,具体实践的比较少,后期写一个实践教程,内容基本都是从参考文章里面抄过来的[看完文章,顺便写做下笔记 ...

  7. 005-优化web请求一-gzip压缩、http缓存控制和缓存校验[Pragma、Expires、Cache-Control、max-age、Last-Modified、用户刷新访问、避免过度304]

    优化Web应用的典型技术:缓存控制头信息.Gzip.应用缓存.ETag.反应型技术[异步方法调用和WebSocket] 一.模板缓存 spring.thymeleaf.cache=true sprin ...

  8. 缓存(CDN缓存,浏览器(客户端)缓存)

    1.什么是缓存? 缓存是一种数据结构,用于快速查找以及执行的操作结果.因此,如果一个操作执行起来很慢,对于常用的输入数据就可以将操作的结果缓存,并在下次调用该操作时使用缓存的数据. 缓存是一个到处都存 ...

  9. host缓存,浏览器缓存---解决host缓存带来的伤

    1.缓存 缓存,对应工程师来讲简直太熟悉了,太方便了,省略到资源或数据的获取方式,直接缓存到离用户访问最快的地方,也降低服务器的压力,比如: (1)静态文件获取 服务器->cdn->本地磁 ...

  10. Web前后端缓存技术(缓存的主要作用是什么)

    Web前后端缓存技术Web前后端缓存技术(缓存的主要作用是什么) 一.总结 一句话总结: 加快页面打开速度 减少网络带宽消耗 降低服务器压力 1.在Web应用中,应用缓存的地方有哪些? 主要有浏览器缓 ...

随机推荐

  1. Spring 依赖注入(DI) 的三种方式 和 对集合类型的注入

    // 分别省略了getter setter public class Student { private String name; private int age; private Teacher t ...

  2. Ha1cyon-CTF 芜湖

    感觉自己还是很欠缺的,尤其是C++的逆向,对stl的不熟悉,直接误导我静态分析了...然后这种题和平常不同的是没有任何混淆和flag验证,需要的是耐心的分析,在过程中,找到线索,这题还考了base64 ...

  3. 计算机网络体系结构整理-第九单元移动IP

    第九章 移动IP 什么是移动:移动指的是用户连接位置的改变,而不是设备物理位置的改变 移动可以是离散的或连续的 移动IP的基本要求:1.IP地址不变 2.宿地址路由 3.信息量和交互简化 4.安全 5 ...

  4. WPF教程十四:了解元素的渲染OnRender()如何使用

    上一篇分析了WPF元素中布局系统的MeasureOverride()和ArrangeOverride()方法.本节将进一步深入分析和研究元素如何渲染它们自身. 大多数WPF元素通过组合方式创建可视化外 ...

  5. jar\war\SpringBoot加载包内外资源的方式,告别FileNotFoundException吧

    工作中常常会用到文件加载,然后又经常忘记,印象不深,没有系统性研究过,从最初的war包项目到现在的springboot项目,从加载外部文件到加载自身jar包内文件,也发生了许多变化,这里开一贴,作为自 ...

  6. echarts堆叠柱状图在最上面的柱子显示总和

    需求 柱子需设置barMinHeight 在堆叠柱状图的最上面显示当前堆叠的总和 直接上代码吧 需要注意:设置barMinHeight时为了让0不显示,只能将0设置为null; 设置为null的柱子l ...

  7. CF1225E题解 Rock Is Push

    在打CF的时候没想到www这个dp真的蛮巧妙的 这是一道dp题(废话 假设我们走到了\((i,j)\)位置,因为我们只能下移/右移,那么我们所有上方与左方的石块(即\(\{ (i,j)|i<n ...

  8. 「CF505E」 Mr. Kitayuta vs. Bamboos

    「CF505E」 Mr. Kitayuta vs. Bamboos 传送门 如果没有每轮只能进行 \(k\) 次修改的限制或者没有竹子长度必须大于 \(0\) 的限制那么直接贪心就完事了. 但是很遗憾 ...

  9. python使用笔记12--操作mysql数据库

    1.创建连接 1 import pymysql 2 connect = pymysql.connect(host='127.0.0.1', 3 user='root', 4 password='123 ...

  10. C语言变量 类型判断

    变量三要素: 一个变量有三个基本的要素,变量的名称,变量的类型,变量的值.所以int a = 10; 变量名为a,变量的存储类型为int型,变量的值为10. 变量还有一些属性如作用范围和存储类型. 变 ...