什么是http缓存呢,当我们使用chrome浏览器,按F12打开控制台,在网络请求中有时候看到状态码是200,有时候状态码是304,当我们去看这种请求的时候,我们会发现状态码为304的状态结果是:Status Code: 304 Not Modified,而状态码为200的时候一般会有四种情况,一种是直接返回200,没有任何其他的标志,另一种是Status Code: 200 OK (from memory cache),还有一种是Status Code: 200 (from disk cache)。最后一种不是太常见,Status Code: 200 (from Service Worker).后面这三种状态码看到的效果是灰色的,其实从给出的信息也能看出来是从缓存中获取上数据。下面我们来详细介绍一下他们都分别是什么时候出现的。

其实我们可以按状态码来区分其为两大类,分别是协商缓存--304和强制缓存--200

协商缓存(304)

这种方式使用到了headers请求头里的两个字段,Last-Modified & If-Modified-Since 。服务器通过响应头Last-Modified告知浏览器,资源最后被修改的时间:

Last-Modified: Thu, 20 Jun 2019 15:58:05 GMT

当再次请求该资源时,浏览器需要再次向服务器确认,资源是否过期,其中的凭证就是请求头If-Modified-Since字段,值为上次请求中响应头Last-Modified字段的值:

If-Modified-Since: Thu, 20 Jun 2019 15:58:05 GMT

浏览器在发送请求的时候服务器会检查请求头request header里面的If-modified-Since,如果最后修改时间相同则返回304,否则给返回头(response header)添加last-Modified并且返回数据(response body)。

另外,浏览器在发送请求的时候服务器会检查请求头(request header)里面的if-none-match的值与当前文件的内容通过hash算法(例如 nodejs: cryto.createHash('sha1'))生成的内容摘要字符对比,相同则直接返回304,否则给返回头(response header)添加etag属性为当前的内容摘要字符,并且返回内容。

综上总结为:

  • 请求头last-modified的日期与响应头的last-modified一致
  • 请求头if-none-match的hash与响应头的etag一致
    这两种情况会返回Status Code: 304

强制缓存(200(from ...))

这里我们使用到了Cache-Control和Expires这两个字段来进行控制,Cache-Control里面可以有多个属性,可以组合设置,其属性有如下几种:

  • max-age=xxx,最大的有效时间 单位秒,是一个相对时间
  • must-revalidate,如果超过了max-age的时间,必须向服务器发送请求,验证资源的有效性
  • no-cache,基本等价于max-age=0,由协商缓存来决定是否缓存资源
  • no-store,真正意义上的不缓存
  • public,代表 http 请求返回的内容所经过的任何路径当中(包括中间一些http代理服务器以及发出请求的客户端浏览器),都可以对返回内容进行缓存操作
  • private,代表只有发起请求的浏览器才可以进行缓存。默认值

比如我们设置

Catch-Control:public,max-age=360000

我们在之前说了强制缓存有三种情况,上面说返回200有四种,第一种其实是不缓存,正常服务器返回响应。

Service Worker

这个东西其实本质上时服务器和客户端之间的代理服务器,一般我们在使用react开发的时候,会发现在根目录出现了一个server-worker.js文件,这个东西就是和service Worker缓存相关的,他会根据网络的状态做出不同的缓存策略,有时候断网了,之前访问过的接口有可能依然会返回数据,其数据来源就是从其缓存中读取。

memory cache

这个是将资源缓存在了内存中。事实上,所有的网络请求都会被浏览器缓存到内存中,当然,内存容量有限,缓存不能无限存放在内存中,因此,注定是个短期缓存。而其控制权在于浏览器。

disk cache

与内存缓存相对的,这个是将资源缓存在硬盘中。虽然相比于内存,硬盘的读取速度要慢很多,但总比没有强。硬盘缓存的控制权在后端,通过什么控制呢?通过HTTP响应头控制,也就是我们在上面说到的catche-control和expires

Expires设置的过期时间是一个绝对的GMT时间,例如:Expires:Thu,20 Jun 2019 20:00:00 GMT; 他告诉浏览器缓存有效性持续到2019年6月20日为止,一直都使用缓存来处理。

Expires有一个非常大的缺陷,它使用一个固定的时间,要求服务器与客户端的时钟保持严格的同步,并且这一天到来后,服务器还得重新设定新的时间。

HTTP1.1引入了Cathe-Control,它使用max-age指定组件被缓存多久,从请求开始在max-age时间内浏览器使用缓存,之外的使用请求,这样就可以消除Expires的限制,

如果对浏览器兼容性要求很高的话,可以两个都使用。

其实在上面说到的Last-Modified对比最后修改时间与Expires一样是有缺陷的,如果,资源的变化的时间间隔小于秒级,比如说是毫秒级的,或者说资源直接是动态生成的,那根据Last-Modified判断,资源就是每时每刻都最新的,即被修改过!

所以,Etag & If-Node-Match 就是来解决这个问题的。
Etag字段的值为文件的特殊标识,一般都是hash生成的,服务器存储着资源的Etag值。接下来的流程都与Lst-Modified & If-Modified-Since一致,只不过,比较的值从最后修改时间变成了Etag值。

Etag的优点在于,对于动态资源或者现在流行的Restful API返回的JSON数据,这些是没有修改时间这一说法的,但是Http标准并没有规定Etag值如何生成,因此我们通过代码自己生成Etag值。当然,计算Etag值会消耗服务器性能。

Cache-Control+Last-Modified+ETag 的优先级会如何?

因为http1.1>http1.0,所以Cache-Control>Expires,ETag>Last-Modified。依照就近原则,先找本地缓存,没有再向服务器发请求,所以Expires>Last-Modified,Cache-Control>ETag,

如果浏览器只支持http1.0,那么浏览器只会携带Last-Modified发送给后台,
如果服务器只支持http1.0,那么服务器会以Last-Modified为标准。
如果浏览器支持http1.1,那么浏览器会携带Cache-Control+Last-Modified+ETag发送给后台,
如果服务器支持http1.1,那么服务器会以Cache-Control+ETag为标准。

200状态码和304状态码何时出现

在没有设置Cache-Contral的情况下,设置Last-Modified和ETag缓存,会出现200(from cache)和304 交替出现的情况。

设置Cache-Contral的情况下,过期刷新会出现304(如果有更新内容,则是200),之后再过期之前刷新都是200(from cache)。如果要确保要向服务端确认,可以将Cache-Contral的max-age设置为0。

通过下图我们可以清晰的明白200和304

https://www.oecom.cn/http-header-control/

区分http请求状态码来理解缓存(协商缓存和强制缓存)的更多相关文章

  1. http协议组成(请求状态码)

    http请求由:请求行:消息报头:请求正文组成 //请求行 Request URL: http://172.32.4.33:8080/operation/v2/autoServer/queryAuto ...

  2. 使用Typescript重构axios(二十七)——添加请求状态码合法性校验

    0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...

  3. http--响应请求状态码

    针对客户端向Web服务器发送的任意一个HTTP请求,不论在何种情况下得到一个响应,每个响应均具有一个由3位数字表示的状态码和相应的描述文字.不同数值的状态码体现了不同类型的响应状态,W3C对响应状态码 ...

  4. 常见的HTTP状态码深入理解

    状态码的职责是当客户端向服务器端发送请求时,描述返回请求结果.借助状态码,用户可以知道服务器端是正常处理了请求,还是出现了什么错误. RFC2616定义的状态码,由3位数字和原因短信组成. 数字中的第 ...

  5. 关于http状态码204理解

    HTTP的状态码有很多种,主要有1xx(临时响应).2xx(成功).3xx(已重定向).4xx(请求错误)以及5xx(服务器错误)五个大类,每个大类还对应一些具体的分类.平时我们接触比较多的是200. ...

  6. Http请求状态码

    1xx - 信息提示   这些状态代码表示临时的响应.客户端在收到常规响应之前,应准备接收一个或多个 1xx 响应.    ·0 - 本地响应成功.   · 100 - Continue 初始的请求已 ...

  7. HTTP网页请求状态码

    我们平时在打开一些网页的时候,会遇到打不开的情况,页面提示404错误,这个404就是http状态码.如果我们可以正常打开网页,这时也会有http状态码的,这个状态码就是200,只不过这时我们是无法通过 ...

  8. http请求状态码解析

    1xx(临时响应) 2xx(成功) 3xx(重定向) 4xx(请求错误) http状态码 400 (错误请求) 服务器不理解请求的语法. http状态码 401 (未授权) 请求要求身份验证. 对于需 ...

  9. 一些常见的HTTP的请求状态码

    200:正确的请求返回正确的结果,如果不想细分正确的请求结果都可以直接返回200. 201:表示资源被正确的创建.比如说,我们 POST 用户名.密码正确创建了一个用户就可以返回 201. 202:请 ...

随机推荐

  1. vue 3.0新特性

    参考:  https://www.cnblogs.com/Highdoudou/p/9993870.html https://www.cnblogs.com/ljx20180807/p/9987822 ...

  2. How to create a angular2 project process

    步骤1. 设置开发环境 在开始工作之前,我们必须设置好开发环境. 如果你的机器上还没有Node.js®和npm 和VScode(因为我是用VS工具来编辑的), 请先安装它们. 然后全局安装 Angul ...

  3. java 精确加减

    /** * 提供精确的加法运算. * @param v1 被加数 * @param v2 加数 * @return 两个参数的和 */ public double add(double v1, dou ...

  4. 如何在ARM上运行k3s? 窥探k3s启动过程!,内附容器多平台包构建

    开始之前 最近在对华为云鲲鹏服务器(一种ARM服务器arm64)运行容器可行性做验证,顺便了解了很多ARM和容器相关的知识.一提到arm运行容器首先想到的是k3s,下面是用k3s快速搭建一个kuber ...

  5. MySQL递归查询

    MySQL8.0已经支持CTE递归查询,举例说明 CREATE TABLE EMP (EMPNO integer NOT NULL, ENAME ), JOB ), MGR integer, HIRE ...

  6. Order by 优化

    写在前面 文章涉及到的 customer 表来源于案例库 sakila,下载地址为 http://downloads.mysql.com/docs/sakila-db.zip MySQL 排序方式 通 ...

  7. Java—JSON串转换成实体Bean对象模板

    介绍 模板需求说明   开发中经常遇到前端传递过来的JSON串的转换,后端需要解析成对象,有解析成List的,也有解析成Map的. 依赖 <dependency> <groupId& ...

  8. [工具推荐]001.FlipPDF使用教程

    FlipPDF是一个什么样的软件呢,他有什么实际用途呢?顾名思义,这是一个跟PDF有关的软件,没错它是一款把PDF转换成酷炫书籍的软件,他还支持PDF中的目录,也就是转换成的书籍,目录一样可以跳转的. ...

  9. 日期类之SimpleDateFormat

    1.System 类下的currentTimeMillis();2.Date类:java.util.Date及其子类java.sql.Date                  如何创建实例:其下的方 ...

  10. Cocos Creator 通用框架设计 —— 资源管理优化

    接着<Cocos Creator 通用框架设计 -- 资源管理>聊聊资源管理框架后续的一些优化: 通过论坛和github的issue,收到了很多优化或bug的反馈,基本上抽空全部处理了,大 ...