Http实战之缓存、重定向(1)

简介: Http实战之缓存、重定向(1)

Http缓存


关于Http缓存这部分内容在网上查阅资料时,发现很多文章将其分为*强制缓存、协商缓存或者对比缓存*,但笔者在RFC文档中并没有找到相关词汇,所以本文并不会采用上述分类,而是以RFC文件及《Http权威指南》中的内容为准。除此之外还需要明确的一点:本文并不讨论【代理缓存】,只分析客户端本身进行缓存的情况。


RFC文档:https://datatracker.ietf.org/doc/html/rfc2616#section-13,中主要涉及到的Http缓存相关的内容如下:

微信图片_20221114123759.png


缓存处理步骤


微信图片_20221114123834.png

整个流程比较简单,可能需要解释的有两个名词


1.判断是否新鲜,也就是新鲜度检测,可以理解为检查缓存是否已经过期

2.服务器再验证,在确认了缓存已经过期的情况我们还需要到服务器去确认过期的缓存是否还有效,如果仍然有效的话此时我们需要将客户端的缓存重新生效,这个过程称之为再验证(revalidation)。


关于第二点小伙伴们可能会有疑问:


为什么确认缓存已经过期了还需要去服务端验证呢,缓存过期不应该直接请求服务器返回最新数据吗?

再验证的话多了一次验证过程不是增加了网络开销了吗?


第一个问题,答:


缓存过期并不意味着缓存中的数据跟服务器保存的数据不一致,例如服务器通过Cache-Control 告诉了客户端缓存有效期为两小时,但在接下来的两小时内服务器上的这份数据并没有任何写入操作,也就是说虽然客户端在检测的时候数据已经过期了,但是客户端此时缓存的数据仍然跟服务器保存的最新数据是一致的,此时也就没必要让服务重新发送一份客户端已经缓存的数据,我们只需要服务器通过某种机制告诉客户端缓存是可用的即可。


第二个问题,答:

缓存的再校验跟向服务器请求最新数据往往会被合并成一个请求。我们可以在发送请求时附加一些用于验证的头信息,比如我们可以给缓存的实体打上一个标签,每次向服务器发送请求时携带上这个标签,当进行再验证时服务器校验客户端当前记录的数据标签是否跟自身保存的一致,如果一致告诉服务器缓存是可用的(304响应码),如果不一致则返回最新数据及最新标签。如下:

微信图片_20221114124012.png

通过前文所述相信大家对Http的缓存机制有了一个大概的了解,那么接下来我们就开始分析其中的细节:如何完成新鲜度检测及再验证?


新鲜度检测

所谓新鲜度检测实际就是检测文档是否过期,服务器可以通过Cache-Control首部和 Expires首部指定返回数据的有效期,Expires是HTTP1.0的规范,使用的是决定时间,如下:


Expires: Wed, 21 Oct 2022 07:28:00 GMT


Cache-Control是HTTP1.1的规范,搭配max-age并使用相对时间,如下:

Cache-Control: max-age=30(单位为秒)


只要在有效期内,客户端即可认为此时的缓存数据是新鲜的,无须向服务器发送请求


再验证

如果客户端检测到此时缓存已经过期,那么需要向服务器发起再验证,一个具有再验证功能的请求跟普通的请求唯一的区别在于请求头中多了一些用于校验的字段,如下:


考: https://datatracker.ietf.org/doc/html/rfc7232

字段名

描述 备注

If-Modified-Since

如果从指定日期之后数据**【被修改】过了则验证失败,需要向服务器发送请求获取最新数据,如果验证成功,服务端返回「304(Not Modified)」**

通过日期校验,通常用于缓存再校验,一般会结合响应头中的Last-Modified使用

If-None-Match

如果缓存中数据的标签跟服务器数据的标签不匹配则验证失败,需要向服务器发送请求获取最新数据,与Etag 服务器响应首部配合使用,如果验证成功,服务端返回**「304(Not Modified)」**

通过唯一标识进行校验,通常用于缓存再校验

1.If-Modified-Since再验证工作过程如下

微信图片_20221114124331.png

客户端在第一次缓存时同时也记录了服务器返回的Last-Modified,再后续发现缓存过期时会向服务器发送一个再验证请求,在请求头中添加一个If-Modified-Since字段,其值为Last-Modified的值,服务器在收到此请求后,先判断在指定时间后数据是否发生了变化,如果没有变化则返回**「304(Not Modified)」**,否则返回200状态码及最新数据。


2.If-None-Match:实体标签再验证

image.png

整个校验过程跟If-Modified-Since是一致的,唯一的区别在于If-Modified-Since校验的是日志,而If-None-Match校验的是数据对应的唯一标签。如果 缓存数据中同时有 Etag 和 Last-Modified 字段的时候, Etag 的优先级更高,也就是先会判断 Etag 是否变化了,如果 Etag 没有变化,然后再看 Last-Modified。


这里需要说明一下,除了上面提到的两个头部字段外,Http中还定义了一些其它的带有校验含义的header,如下:

字段名

描述

备注

If-Match

与Etag 服务器响应首部配合使用,校验失败返回**「412(Precondition Failed)」**

并不用于缓存相关操作,而是用于避免错误的更新操作(PUT、POST、DELETE),只有在满足条件的情况下才允许更新,通常用于多人协作更新同一份数据时

If-Unmodified-Since

如果从指定日期之后数据**【未被修改】则验证成功。验证失败时服务端需要返回「412(Precondition Failed)」**

跟If-Match一样能避免错误的更新操作,不同的是If-Match比较的是标签而If-Unmodified-Since比较的是日期。另外在进行部分文件的传输时,获取文件的其余部分之前,要确保文件未发生变化,此时这个首部是非常有用的。例如在端点续传的场景下,需要保证服务端已经传送到客户端的资源没有发生变化。


If-Range

支持对不完整文档的缓存,会搭配服务器响应中的Last-Modified或者ETag使用,验证失败时服务端需要返回**「412(Precondition Failed)」**

主要用于范围请求或断点续传

读者朋友们需要注意的是,虽然If-Match、If-Unmodified-Since看起来是If-None-Match跟If-Modified-Since的反义词,但在HTPP协议中定义的语义是完全不一样的。具体可以参考:https://datatracker.ietf.org/doc/html/rfc7232#page-17



相关文章
|
4月前
|
缓存 安全 Android开发
Android经典实战之用Kotlin泛型实现键值对缓存
本文介绍了Kotlin中泛型的基础知识与实际应用。泛型能提升代码的重用性、类型安全及可读性。文中详细解释了泛型的基本语法、泛型函数、泛型约束以及协变和逆变的概念,并通过一个数据缓存系统的实例展示了泛型的强大功能。
45 2
|
2月前
|
存储 缓存 NoSQL
保持HTTP会话状态:缓存策略与实践
保持HTTP会话状态:缓存策略与实践
|
2月前
url重写重定向所有http网址到https网址
url重写重定向所有http网址到https网址
39 4
|
2月前
|
存储 缓存 监控
HTTP:强缓存优化实践
HTTP强缓存是提升网站性能的关键技术之一。通过精心设计缓存策略,不仅可以显著减少网络延迟,还能降低服务器负载,提升用户体验。实施上述最佳实践,结合持续的监控与调整,能够确保缓存机制高效且稳定地服务于网站性能优化目标。
57 3
|
3月前
|
数据安全/隐私保护 Docker 容器
配置Harbor支持https功能实战篇
关于如何配置Harbor支持HTTPS功能的详细教程。
139 12
配置Harbor支持https功能实战篇
|
3月前
|
分布式计算 Hadoop Devops
Hadoop集群配置https实战案例
本文提供了一个实战案例,详细介绍了如何在Hadoop集群中配置HTTPS,包括生成私钥和证书文件、配置keystore和truststore、修改hdfs-site.xml和ssl-client.xml文件,以及重启Hadoop集群的步骤,并提供了一些常见问题的故障排除方法。
93 3
Hadoop集群配置https实战案例
|
3月前
|
机器学习/深度学习 JSON API
HTTP协议实战演练场:Python requests库助你成为网络数据抓取大师
在数据驱动的时代,网络数据抓取对于数据分析、机器学习等至关重要。HTTP协议作为互联网通信的基石,其重要性不言而喻。Python的`requests`库凭借简洁的API和强大的功能,成为网络数据抓取的利器。本文将通过实战演练展示如何使用`requests`库进行数据抓取,包括发送GET/POST请求、处理JSON响应及添加自定义请求头等。首先,请确保已安装`requests`库,可通过`pip install requests`进行安装。接下来,我们将逐一介绍如何利用`requests`库探索网络世界,助你成为数据抓取大师。在实践过程中,务必遵守相关法律法规和网站使用条款,做到技术与道德并重。
60 2
|
3月前
|
数据采集 网络协议 API
HTTP协议大揭秘!Python requests库实战,让网络请求变得简单高效
【9月更文挑战第13天】在数字化时代,互联网成为信息传输的核心平台,HTTP协议作为基石,定义了客户端与服务器间的数据传输规则。直接处理HTTP请求复杂繁琐,但Python的`requests`库提供了一个简洁强大的接口,简化了这一过程。HTTP协议采用请求与响应模式,无状态且结构化设计,使其能灵活处理各种数据交换。
90 8
|
4月前
|
缓存 NoSQL 数据库
go-zero微服务实战系列(五、缓存代码怎么写)
go-zero微服务实战系列(五、缓存代码怎么写)
|
3月前
|
Python
HTTP协议不再是迷!Python网络请求实战,带你走进网络世界的奥秘
本文介绍了HTTP协议,它是互联网信息传递的核心。作为客户端与服务器通信的基础,HTTP请求包括请求行、头和体三部分。通过Python的`requests`库,我们可以轻松实现HTTP请求。本文将指导你安装`requests`库,并通过实战示例演示如何发送GET和POST请求。无论你是想获取网页内容还是提交表单数据,都能通过简单的代码实现。希望本文能帮助你在Python网络请求的道路上迈出坚实的一步。
73 0