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月前
|
缓存 并行计算 监控
vLLM 性能优化实战:批处理、量化与缓存配置方案
本文深入解析vLLM高性能部署实践,揭秘如何通过continuous batching、PagedAttention与前缀缓存提升吞吐;详解批处理、量化、并发参数调优,助力实现高TPS与低延迟平衡,真正发挥vLLM生产级潜力。
1015 0
vLLM 性能优化实战:批处理、量化与缓存配置方案
|
5月前
|
存储 缓存 NoSQL
Redis专题-实战篇二-商户查询缓存
本文介绍了缓存的基本概念、应用场景及实现方式,涵盖Redis缓存设计、缓存更新策略、缓存穿透问题及其解决方案。重点讲解了缓存空对象与布隆过滤器的使用,并通过代码示例演示了商铺查询的缓存优化实践。
271 1
Redis专题-实战篇二-商户查询缓存
|
6月前
|
运维 网络协议 安全
为什么经过IPSec隧道后HTTPS会访问不通?一次隧道环境下的实战分析
本文介绍了一个典型的 HTTPS 无法访问问题的排查过程。问题表现为 HTTP 正常而 HTTPS 无法打开,最终发现是由于 MTU 设置不当导致报文被丢弃。HTTPS 因禁止分片,对 MTU 更敏感。解决方案包括调整 MSS 或中间设备干预。
|
8月前
|
Java 测试技术 容器
Jmeter工具使用:HTTP接口性能测试实战
希望这篇文章能够帮助你初步理解如何使用JMeter进行HTTP接口性能测试,有兴趣的话,你可以研究更多关于JMeter的内容。记住,只有理解并掌握了这些工具,你才能充分利用它们发挥其应有的价值。+
1235 23
|
6月前
|
数据采集 JSON Go
Go语言实战案例:实现HTTP客户端请求并解析响应
本文是 Go 网络与并发实战系列的第 2 篇,详细介绍如何使用 Go 构建 HTTP 客户端,涵盖请求发送、响应解析、错误处理、Header 与 Body 提取等流程,并通过实战代码演示如何并发请求多个 URL,适合希望掌握 Go 网络编程基础的开发者。
|
7月前
|
JSON 前端开发 Go
Go语言实战:创建一个简单的 HTTP 服务器
本篇是《Go语言101实战》系列之一,讲解如何使用Go构建基础HTTP服务器。涵盖Go语言并发优势、HTTP服务搭建、路由处理、日志记录及测试方法,助你掌握高性能Web服务开发核心技能。
|
7月前
|
存储 缓存 安全
Go语言实战案例-LRU缓存机制模拟
本文介绍了使用Go语言实现LRU缓存机制的方法。LRU(最近最少使用)是一种常见缓存淘汰策略,当缓存满时,优先删除最近最少使用的数据。实现中使用哈希表和双向链表结合的方式,确保Get和Put操作均在O(1)时间内完成。适用于Web缓存、数据库查询优化等场景。
|
7月前
|
Web App开发 缓存 数据安全/隐私保护
Django全栈实战:HTTP状态码与业务状态码的分层设计与实战应用
HTTP状态码是服务器响应请求的3位数字代码,分为1xx(信息)、2xx(成功)、3xx(重定向)、4xx(客户端错误)、5xx(服务器错误)。业务状态码则用于描述具体业务逻辑结果,常在响应体中返回。二者在前后端交互中有不同用途和处理方式。本文还介绍了如何在Django项目中设计并使用业务状态码。
600 0
|
9月前
|
缓存 搜索推荐 CDN
HTTP缓存策略的区别和解决的问题
总的来说,HTTP缓存策略是一种权衡,需要根据具体的应用场景和需求来选择合适的策略。理解和掌握这些策略,可以帮助我们更好地优化网页性能,提高用户的浏览体验。
254 11
|
10月前
|
缓存 安全 Java
深入解析HTTP请求方法:Spring Boot实战与最佳实践
这篇博客结合了HTTP规范、Spring Boot实现和实际工程经验,通过代码示例、对比表格和架构图等方式,系统性地讲解了不同HTTP方法的应用场景和最佳实践。
956 5