什么是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. ruoyi-plus-server(一):引入Mybatis-Plus

    背景:著名开源管理系统ruoyi-vue是基于SpringBoot,Spring Security,JWT,Vue & Element 的前后端分离权限管理系统(https://gitee.c ...

  2. firefox的fq设置图文教程- 【windows,mac通用】

    不能像下图一样全部设置socket代理,这样会把所以请求都转发到ss ! 应该使用系统设置,这里不能用pac ,因为pac 链接每次都是变化的. 搞定.

  3. Spark Streaming与流处理

    Spark Streaming与流处理 ​ 一.流处理        1.1 静态数据处理        1.2 流处理二.Spark Streaming        2.1 简介        2 ...

  4. Python+Selenium+Chrome 的一个案例

    第一步,下载chromeDrive:http://npm.taobao.org/mirrors/chromedriver(我下载的是2.43版本的chromedriver_win32.zip) 下载之 ...

  5. css3弹性布局

    二.弹性布局(重点******************************************) 1.什么是弹性布局 弹性布局,是一种布局方式. 主要解决的是某个元素中子元素的布局方式 让页面 ...

  6. poj2823单调队列认知

    Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 62930   Accepted: 17963 ...

  7. docker-compose 命令详解

    1.docker-compose的使用非常类似于docker命令的使用,但是需要注意的是大部分的compose命令都需要到docker-compose.yml文件所在的目录下才能执行. 2.[Linu ...

  8. PHP 获取当前目录下的所有文件

    我们有时候会想拿到当前目录下的所有文件名,以下就是我写的一个方法,请大家参考 // 获取当前文件的上级目录 $con = dirname(__FILE__); // 扫描$con目录下的所有文件 $f ...

  9. Ajax长轮询(LongPoll)

    1)HTML HTTP是无状态.单向的协议,用户只能够通过客服端向服务器发送请求并由服务器处理发回一个响应.若要实现聊天室.WEBQQ.在线客服.邮箱等这些即时通讯的应用,就要用到“ 服务器推送技术( ...

  10. CSS基础选择器总结

    基础选择器 作用 特点 使用情况 用法 标签选择器 可以选出所有相同的标签,比如p 不能差异化选择 较多 p {color:red;} 类选择器 可以选出1个或多个标签 可以根据需求选择 非常多 .n ...