干货 | 彻底弄懂 HTTP 缓存机制及原理

转载自  干货 | 彻底弄懂 HTTP 缓存机制及原理

前言

Http 缓存机制作为 web 性能优化的重要手段,对于从事 Web 开发的同学们来说,应该是知识体系库中的一个基础环节,同时对于有志成为前端架构师的同学来说是必备的知识技能。

但是对于很多前端同学来说,仅仅只是知道浏览器会对请求的静态文件进行缓存,但是为什么被缓存,缓存是怎样生效的,却并不是很清楚。

在此,我会尝试用简单明了的文字,像大家系统的介绍HTTP缓存机制,期望对各位正确的理解前端缓存有所帮助。

 

在介绍HTTP缓存之前,作为知识铺垫,先简单介绍一下HTTP报文

HTTP报文就是浏览器和服务器间通信时发送及响应的数据块。

浏览器向服务器请求数据,发送请求(request)报文;服务器向浏览器返回数据,返回响应(response)报文。

报文信息主要分为两部分

1.包含属性的首部(header)--------------------------附加信息(cookie,缓存信息等)与缓存相关的规则信息,均包含在header中

2.包含数据的主体部分(body)-----------------------HTTP请求真正想要传输的部分



缓存规则解析

为方便大家理解,我们认为浏览器存在一个缓存数据库,用于存储缓存信息。

在客户端第一次请求数据时,此时缓存数据库中没有对应的缓存数据,需要请求服务器,服务器返回后,将数据存储至缓存数据库中。

HTTP缓存有多种规则,根据是否需要重新向服务器发起请求来分类,我将其分为两大类(强制缓存,对比缓存)。

在详细介绍这两种规则之前,先通过时序图的方式,让大家对这两种规则有个简单了解。


已存在缓存数据时,仅基于强制缓存,请求数据的流程如下

已存在缓存数据时,仅基于对比缓存,请求数据的流程如下

对缓存机制不太了解的同学可能会问,基于对比缓存的流程下,不管是否使用缓存,都需要向服务器发送请求,那么还用缓存干什么?

这个问题,我们暂且放下,后文在详细介绍每种缓存规则的时候,会带给大家答案。可以点击此处查看浏览器的缓存机制。

我们可以看到两类缓存规则的不同,强制缓存如果生效,不需要再和服务器发生交互,而对比缓存不管是否生效,都需要与服务端发生交互。
两类缓存规则可以同时存在,强制缓存优先级高于对比缓存,也就是说,当执行强制缓存的规则时,如果缓存生效,直接使用缓存,不再执行对比缓存规则。


强制缓存

从上文我们得知,强制缓存,在缓存数据未失效的情况下,可以直接使用缓存数据,那么浏览器是如何判断缓存数据是否失效呢?

我们知道,在没有缓存数据的时候,浏览器向服务器请求数据时,服务器会将数据和缓存规则一并返回,缓存规则信息包含在响应header中。

对于强制缓存来说,响应header中会有两个字段来标明失效规则(Expires/Cache-Control),使用chrome的开发者工具,可以很明显的看到对于强制缓存生效时,网络请求的情况。可以点击此处查看浏览器的缓存机制。



Expires

Expires的值为服务端返回的到期时间,即下一次请求时,请求时间小于服务端返回的到期时间,直接使用缓存数据。

不过Expires 是HTTP 1.0的东西,现在默认浏览器均默认使用HTTP 1.1,所以它的作用基本忽略。

另一个问题是,到期时间是由服务端生成的,但是客户端时间可能跟服务端时间有误差,这就会导致缓存命中的误差。
所以HTTP 1.1 的版本,使用Cache-Control替代。

Cache-Control
Cache-Control 是最重要的规则。常见的取值有private、public、no-cache、max-age,no-store,默认为private。
private:             客户端可以缓存
public:              客户端和代理服务器都可缓存(前端的同学,可以认为public和private是一样的)
max-age=xxx:   缓存的内容将在 xxx 秒后失效
no-cache:          需要使用对比缓存来验证缓存数据(后面介绍)
no-store:           所有内容都不会缓存,强制缓存,对比缓存都不会触发(对于前端开发来说,缓存越多越好,so...基本上和它说886)

举个板栗

图中Cache-Control仅指定了max-age,所以默认为private,缓存时间为31536000秒(365天)
也就是说,在365天内再次请求这条数据,都会直接获取缓存数据库中的数据,直接使用。

对比缓存

对比缓存,顾名思义,需要进行比较判断是否可以使用缓存。

浏览器第一次请求数据时,服务器会将缓存标识与数据一起返回给客户端,客户端将二者备份至缓存数据库中。

再次请求数据时,客户端将备份的缓存标识发送给服务器,服务器根据缓存标识进行判断,判断成功后,返回304状态码,通知客户端比较成功,可以使用缓存数据。


第一次访问:


再次访问:

通过两图的对比,我们可以很清楚的发现,在对比缓存生效时,状态码为304,并且报文大小和请求时间大大减少。

原因是,服务端在进行标识比较后,只返回header部分,通过状态码通知客户端使用缓存,不再需要将报文主体部分返回给客户端。

对于对比缓存来说,缓存标识的传递是我们着重需要理解的,它在请求header和响应header间进行传递,一共分为两种标识传递,接下来,我们分开介绍。


Last-Modified  /  If-Modified-Since
Last-Modified:
服务器在响应请求时,告诉浏览器资源的最后修改时间。

If-Modified-Since:
再次请求服务器时,通过此字段通知服务器上次请求时,服务器返回的资源最后修改时间。

服务器收到请求后发现有头If-Modified-Since 则与被请求资源的最后修改时间进行比对。

若资源的最后修改时间大于If-Modified-Since,说明资源又被改动过,则响应整片资源内容,返回状态码200;
若资源的最后修改时间小于或等于If-Modified-Since,说明资源无新修改,则响应HTTP 304,告知浏览器继续使用所保存的cache。



Etag  /  If-None-Match(优先级高于Last-Modified  /  If-Modified-Since)


Etag:
服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器决定)。

If-None-Match:
再次请求服务器时,通过此字段通知服务器客户段缓存数据的唯一标识。
服务器收到请求后发现有头If-None-Match 则与被请求资源的唯一标识进行比对,
不同,说明资源又被改动过,则响应整片资源内容,返回状态码200;
相同,说明资源无新修改,则响应HTTP 304,告知浏览器继续使用所保存的cache。


总结

对于强制缓存,服务器通知浏览器一个缓存时间,在缓存时间内,下次请求,直接用缓存,不在时间内,执行比较缓存策略。可以点击此处查看浏览器的缓存机制。

对于比较缓存,将缓存信息中的Etag和Last-Modified通过请求发送给服务器,由服务器校验,返回304状态码时,浏览器直接使用缓存。

浏览器第一次请求:


浏览器再次请求时:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/326874.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实习知识整理7:SpringBoot和html+thymeleaf模板的项目的相关配置文件

1. application.yml server: port: 8082servlet:context-path: /project #设置访问地址 http://localhost:8082/project 才可以访问到 static 下 index.htmlspring:datasource: # 数据库driver-class-name: com.mysql.cj.jdbc.Driver # 这是8的配置,5的话不用…

Visual Basic的未来之路

上周,微软宣布了他们改变Visual Basic语言未来发展计划的想法。这次公布给Visual Basic开发人员留下了很多不确定性,但Visual Basic语言的设计者Anthony D.Green说明了这个新策略的一些细节。 Green首先列出了当时使用VB进行开发的四个基础指导原则&…

快速排序+思路分析

图解 代码实现 package com.atguigu.sort;import com.sun.org.apache.xpath.internal.WhitespaceStrippingElementMatcher;import java.util.Arrays;/*** 创建人 wdl* 创建时间 2021/3/22* 描述*/ public class QuickSort {public static void main(String[] args) {//[-9,78,…

jquery sleep函数

function sleep(n) { //n表示的毫秒数 var start new Date().getTime(); while (true) if (new Date().getTime() - start > n) break; } console.log(new Date()); this.sleep(3000); console.log(new Date());

2017 年编程语言排行榜:Python 排第一

站长之家(ChinaZ.com) 7 月 24 日消息,近日根据 IEEE Spectrum 发布的研究报告显示,在 2016 年排名第三的 Python 在今年已经成为世界上最受欢迎的语言,C 和 Java 分别位居第二和第三位。IEEE Spectrum 的排行依据数据记者 Nick Diakopoulos …

Spring 获取 request 的几种方法及其线程安全性分析

转载自 Spring 获取 request 的几种方法及其线程安全性分析 本文将介绍在Spring MVC开发的Web系统中,获取request对象的几种方法,并讨论其线程安全性。 一、概述 在使用Spring MVC开发Web系统时,经常需要在处理请求时使用request对象&…

2的负x次幂图像_数学| NO.2,3 函数 T15

点击蓝字,关注我们函数题目2020.11.30#2,3函数 T15函数发展:函数就是在某变化过程中有两个变量X和Y,变量Y随着变量X一起变化,而且依赖于X。如果变量X取某个特定的值,Y依确定的关系取相应的值,那么称Y是X的函…

AspNet Identity 和 Owin 谁是谁

英文原文:http://tech.trailmax.info/2014/08/aspnet-identity-and-owin-who-is-who/ 最近我发现Stackoverflow上有一个非常好的问题.提问者问:为什么在调用AuthenticationManager.SignIn后,claim仍然可以被添加到Identity并持久化到cookie里. 示例代码如下所示: ClaimsIdenti…

jquery中获取下拉框的文本值

获取下拉框的属性值:$(this).val(); 获取下拉框的文本值:$(this).find(option:selected).text();

快速排序+时间测试(yyds)

package com.atguigu.sort;import com.sun.org.apache.xpath.internal.WhitespaceStrippingElementMatcher;import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date;/*** 创建人 wdl* 创建时间 2021/3/22* 描述*/ public class QuickSort {public…

ssh根据姓名查询的时候报错java.lang.IndexOutOfBoundsException: Remember that

错误如下:java.lang.IndexOutOfBoundsException: Remember that ordinal parameters are 1-based!at org.hibernate.engine.query.ParameterMetadata.getOrdinalParameterDescriptor(ParameterMetadata.java:79)at org.hibernate.engine.query.ParameterMetadata.ge…

bs架构 erp 进销存_从应用架构看生鲜电商信息化建设

编辑导读:对于生鲜电商来说,信息化建设是很重要的一环,所有的业务开展都离不开信息化的支持。本文作者讲从应用架构角度出发,对生鲜电商信息化建设展开分析,希望对你有帮助。一、背景语言共识之前介绍了从业务架构看生…

java中int转成String位数不足前面补零 java格式化2位数不足补零

最近我又搜了关于String.format的东西,其实有自带的补零方法, String.format("%06d",12);//其中0表示补零而不是补空格,6表示至少6位

分布式 | Dubbo 架构设计详解

转载自 分布式 | Dubbo 架构设计详解 Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。从服务模型的角度来看,Dubbo采用的是一…

完成OSS.Http底层HttpClient重构封装 支持标准库

OSS.Http项目对于.Net Standard标准库的支持已经迁移完毕,OSS开源系列两个最底层的类库已经具备跨运行时支持的能力。由于OSS.Http类库是几年前我参照RestSharp的思路,完成的一个轻量型Http请求框架。由于时间较久底层使用的还是HttpWebRequest&#xff…

归并排序+思路分析

思路分析 代码实现 package com.atguigu.sort;import java.util.Arrays;/*** 创建人 wdl* 创建时间 2021/3/22* 描述*/ public class MergeSort {public static void main(String[] args) {int arr[]{8,4,5,7,1,3,6,2};int temp[]new int[arr.length];mergeSort(arr,0,arr.len…

java中判断 101-200 之间有多少个素数,并输出所有的素数

题目:判断 101-200 之间有多少个素数,并输出所有的素数 素数是什么: 质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数。 那么题目的答案如下&#xff…

常数除以0的极限是什么_【极限】第四节 极限运算法则

定理 例题 极限运算法则就像加减乘除四则运算一样,是一种计算规则,那么极限也有属于它自己的一套计算规则。 极限运算法则的常用定理 定理1 两个无穷小的和是无穷小 有限个无穷小之和也是无穷小 定理2 有界函数与无穷小的乘积是无穷小 常数与无穷小的乘积…

mysql修改字段 新增字段

ALTER TABLE house change flag flag tinyint(2) DEFAULT 1 COMMENT 1自住 2出租 3空置 ; ALTER TABLE house change house_type house_type int(10) DEFAULT 1 COMMENT 房间类型1住宅、2公寓、3办公、4店铺、5酒店、6别墅、0其他; ALTER TABLE account_rule_config ADD rule…

用JAVASCRIPT实现静态对象、静态方法和静态属性

转载自 用JAVASCRIPT实现静态对象、静态方法和静态属性 Javascript语言的面向对象特征很弱,其他面向对象语言在创建类时只要使用关键字static即可指定类为静态类,Javascript没有提供static这样的关键字,要让Javascript也具有“静态”特性只…