Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >rfc7234之http缓存

rfc7234之http缓存

作者头像
用户1215536
发布于 2023-05-03 02:07:56
发布于 2023-05-03 02:07:56
35100
代码可运行
举报
运行总次数:0
代码可运行

声明:本人原创文章,详细内容已发布在我的微信个人技术公众号---网络技术修炼,公众号总结普及网络基础知识,包括基础原理、网络方案、开发经验和问题定位案例等,欢迎关注。

缓存概念

缓存处理请求步骤

缓存如果查询到某个请求已经有缓存,那么需要进一步检查该资源的新鲜度,根据新鲜度和请求中的字段综合评估是否要去服务端拉取新鲜的资源。

注意:

  • 创建响应时候要注意版本匹配,如果服务器响应和客户端请求的http版本不一致,要在缓存服务器做转换。
  • 缓存有通用的日志规范,常见的日志为Squid日志格式和网景的可扩展通用日志。
  • 缓存中过期的资源也不一定要删除,因为过期了也能用,删除一般采用特定算法,如LRU。

以http get为例缓存处理逻辑如下图所示。

服务端响应写入缓存

相关http字段

  • 缓存服务器如果不支持Range和Content-Range,那么不要缓存不完整的response。
  • 缓存服务器在未接收完一个Content-Range的content时候,不要给客户端该部分的应答。
  • 缓存服务器可以将多个Content-Range的content片段组合到一起应答给客户端。

缓存响应的创建

Vary

Vary 是一个HTTP响应头部信息,它决定了对于未来的一个请求头,应该使用一个缓存作为响应还是向源服务器请求一个新的响应。当响应中有vary字段的时候,缓存时候必须将vary字段一并缓存,下次请求的时候除了url外,还需要与vary缓存的字段完全一致才可以返回缓存内容。

例如,如果响应的 Vary 字段设置为 "Accept-Language",那么在缓存响应时,代理服务器和客户端应该按照请求中的 Accept-Language 字段来区分不同的响应。这意味着,如果一个客户端发出了两个不同的请求,其中一个请求的 Accept-Language 字段是 "en-US",另一个请求的 Accept-Language 字段是 "fr-FR",那么这两个请求应该获得不同的响应。

如果 Vary 字段为空,那么代理服务器和客户端可以缓存响应,并在任何请求中重用它。

内容协商除了vary,主要靠Accept来实现,Accept 字段,详见下表:

请求头字段

说明

响应头字段

Accept

告知服务器发送何种媒体类型

Content-Type

Accept-Language

告知服务器发送何种语言

Content-Language

Accept-Charset

告知服务器发送何种字符集

Content-Type

Accept-Encoding

告知服务器采用何种压缩方式

Content-Encoding

新鲜度

相关http字段

判断一个缓冲是否过期可以使用以下公式:

response_is_fresh=freshness_lifetime > current_age

其中freshness_lifetime为新鲜度声明周期,current_age为缓存已经生存的时间,这两个值都是使用的相对时间,后面有详细的计算方法。

注意:这个计算只能说明缓存中的内容是否新鲜,具体能否直接将该内容回复给客户端,还需要结合请求头中cache-control的max-age、max-stale、min-fresh字段进行综合判定。这个也比较好理解比如客户购买了一个苹果,吃的时候会看一下是否在保质期内,刚刚就是计算是否在保质期内,但不同人的处理可能不同,有的人发现过期两天也会吃,有的人发现临近过期就不吃了,请求中cache-control的max-age、max-stale、min-fresh字段就代表了不同处理方式的人。综上,关于缓存服务器对于一个存在的缓存资源是否能直接返回给客户端应该先计算freshness_lifetime - current_age,然后再综合请求中cache-control判断。

freshness_lifetime的计算

新鲜度生命时间(freshness_lifetime)表示资源从诞生到过期的相对时间(以秒为单位),其计算按照如下优先级依次计算,如果某个优先级的字段符合计算条件则跳过后面的计算:

推荐使用Date和Last-Modified 计算的缓存间隔时间除以10,即:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if ((last_modified > 0) && (date > 0) && (date - last_modified) > 0) {
    return (date - last_modified) / 10;
}
current_age的计算

current_age表示资源从诞生到现在的相对时间( 以秒为单位),其参与current_age的计算的因素有:

  • Age字段表示实体从产生到现在以秒为单位经过多长时间了(多级缓存的场景,上一级缓存会填充该字段)。
  • Date字段表示报文内容在源服务器中诞生的时间。
  • 主机时间。

计算方法:

方法1: 用收到响应的时间减去Date字段的值。

用response_time表示收到响应的时间,用date_value表示Date字段的值,那么

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
current_age = response_time - date_value

但是,接收端和源服务器间很可能会有clock skew(时钟偏差),为了防止这种情况,将负数结果赋值为0,所以该计算方案最终为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
current_age = max(0, response_time - date_value)

方法2:逐跳计算。

接收端收到响应报文时的Age值等于上一跳节点中缓存的Age值加上传输时延。用previous_hop_age_value表示上一跳节点中缓存对的Age值,用response_delay表示传输时延,那么计算公式如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
current_age = previous_hop_age_value + response_delay

respose_delay可以粗略地计算为得到响应时间减去发出请求的时间,这里你可能会问,为什么不要再除以二呢,因为HTTP对Age的计算策略是宁可多算也不肯少算的,多算顶多缓存新鲜时间变短,产生额外的新鲜度验证,但是少算的话,即使过期了,客户端还会把它当成新鲜的用。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
response_delay = response_time - request_time

这种方法的好处是response_time和request_time都是本地的时间,不存在时间偏差。

综上所述,通常响应报文的计算会综合上述两种方法,取最大的一个。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#第一种计算方式
age_value_by_date = max(0, response_time - date_value)
#第二种计算方式
response_delay = response_time - request_time
age_value_by_hop = previous_hop_age_value + response_delay
#两种取大的
current_age = max(age_value_by_date, age_value_by_hop)

校验

相关http头
  • 条件验证通过服务器回复304 Not Modified,再验证实效返回200 ok。
  • 条件验证标签如果同时存在为“与”的逻辑关系,都满足才能返回304 Not Modified。

缓存控制

Cache-Control为http1.1上定义的缓存控制策略。

TODO:请求中优先级是什么,比如no-cache和only-if-cached如果同时存在,需要去服务端条件get吗?

其他

Pragma

Pragma: no-cache 含义与Cache-Control:no-cache相同,是为了兼容http 1.0版本的字段,当报文头同时出现Cache-Control和Pragma时候,Pragma被忽略。

Cache Control Extensions

详见:https://httpwg.org/specs/rfc7234.html#cache.control.extensions

Warning

此信息通常用于警告应用于消息有效负载的缓存操作或转换可能引入的错误。详细解释见:https://httpwg.org/specs/rfc7234.html#header.warning

Age

current_age的计算章节已经提到Age字段表示实体从产生到现在以秒为单位经过多长时间了源站服务器不会添加字段,但是缓存服务器会添加,也为多级缓存计算current_age提供了一个重要参数。详见:https://httpwg.org/specs/rfc7234.html#header.age

Via

Via 是一个通用首部,是由代理服务器添加的,适用于正向和反向代理,在请求和响应首部中均可出现。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-04-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
[译] HTTP 缓存头部 - 完全指南
原文: http://cncc.bingj.com/cache.aspx?q=max-age+expires+Last-Modified&d=4997458151473641&mkt=en-US&se
江米小枣
2020/06/16
1.3K0
[译] HTTP 缓存头部 - 完全指南
java http缓存
HTTP/1.1中缓存的目的是为了在很多情况下减少发送请求,也即直接返回缓存;同时在许多情况下可以不需要发送完整响应。前者减少了网络回路的数量,挺高响应速度,HTTP利用一个“过期(expiration)”机制来为此目的。后者减少了网络应用的带宽,HTTP用“验证(validation)”机制来为此目的。 HTTP定义了3种缓存机制: l Freshness allows a response to be used without re-checking it on the origin server, a
xiangzhihong
2018/02/01
1.3K0
跟我一起探索 HTTP-HTTP缓存
可复用性有几个优点。首先,由于不需要将请求传递到源服务器,因此客户端和缓存越近,响应速度就越快。最典型的例子是浏览器本身为浏览器请求存储缓存。
用户1418987
2023/10/16
4540
跟我一起探索 HTTP-HTTP缓存
一篇文章带你详解 HTTP 协议之报文首部及字段详解(中)
先来回顾一下首部字段在报文的位置,HTTP 报文包含报文首部和报文主体,报文首部包含请求行(或状态行)和首部字段。 在报文众多的字段当中,HTTP 首部字段包含的信息最为丰富。首部字段同时存在于请求和响应报文内,并涵盖 HTTP 报文相关的内容信息。使用首部字段是为了给客服端和服务器端提供报文主体大小、所使用的语言、认证信息等内容。
java进阶架构师
2018/08/15
2.1K0
一篇文章带你详解 HTTP 协议之报文首部及字段详解(中)
【浏览器】:缓存
缓存是一种保存资源副本并在下次请求时直接使用该副本的技术。当 web 缓存发现请求的资源已经被存储,它会拦截请求,返回该资源的拷贝,而不会去源服务器重新下载。缓存的种类有很多,其大致可归为两类:
WEBJ2EE
2020/11/20
9910
【浏览器】:缓存
【HTTP】缓存
随着用户访问量越来越大,缓存变得越来越重要。HTTP文件缓存可以减少冗余数据的传输;缓解网络瓶颈;降低对原始服务器的请求;以及降低距离延迟。
奋飛
2019/08/14
7070
用ASP.NET Core 2.1 建立规范的 REST API -- 缓存和并发
本文所需的一些预备知识可以看这里: http://www.cnblogs.com/cgzl/p/9010978.html 和 http://www.cnblogs.com/cgzl/p/9019314.html
solenovex
2018/08/01
7330
用ASP.NET Core 2.1 建立规范的 REST API -- 缓存和并发
七、《图解HTTP》- HTTP首部和HTTP协作服务器
虽然平时感受不到,但是却是互联网天天在用的东西,这本书花了50多页的内容介绍它,可见它的重要性。
阿东
2022/08/12
1.9K0
七、《图解HTTP》- HTTP首部和HTTP协作服务器
浅谈浏览器HTTP的缓存机制
针对浏览器的http缓存的分析也算是老生常谈了,每隔一段时间就会冒出一篇不错的文章,其原理也是各大公司面试时几乎必考的问题。
哲洛不闹
2018/09/18
7690
浅谈浏览器HTTP的缓存机制
HTTP系列之:HTTP缓存
为了提高网站的访问速度和效率,我们需要设计各种各样的缓存,通过缓存可以避免不必要的额外数据传输和请求,从而提升网站的请求速度。对于HTTP协议来说,本身就自带有HTTP缓存。
程序那些事
2021/09/01
8610
[日常] HTTP的缓存
web缓存: 1.可以自动保存常见文档副本的HTTP设备,当web请求抵达缓存时,如果存在缓存副本,就直接从本地存储设备返回,而不是去源服务器获取 2.缓存命中和未命中 3.HTTP再验证,检测服务器上的内容是否发生了变化,新鲜度检测规则。缓存对副本进行再验证时,会向服务器发送一个小的再验证请求,如果没变化,服务器会返回304 Not Modified,get请求中添加if-modified-since会进行再验证 4.缓存命中率:由缓存提供服务的占比,命中率与缓存大小,用户兴趣相似点,数据的变化,缓
唯一Chat
2019/09/10
4290
[日常] HTTP的缓存
HTTP缓存
P.S.关于HTTP Header的更多信息,请查看4.2 Message Headers
ayqy贾杰
2019/06/12
9930
HTTP协议详解
利用 TCP/IP 协议族进行网络通信时,会通过分层顺序与对方进行通信。发送端从应用层往下走,接收端则从链路层往上走。如下:
小柒吃地瓜
2020/04/23
2.2K0
你还在为 HTTP 的这些概念头疼吗?
上一篇文章我们大致讲解了一下 HTTP 的基本特征和使用,大家反响很不错,那么本篇文章我们就全面一下 HTTP 的特性。我们接着上篇文章没有说完的 HTTP 标头继续来介绍(此篇文章会介绍所有标头的概念,但没有深入底层)
cxuan
2020/02/19
2.5K0
你还在为 HTTP 的这些概念头疼吗?
浏览器缓存机制剖析
“缓存一直是前端优化的主战场,利用好缓存就成功了一半。本篇从HTTP请求和响应的头域入手,让你对浏览器缓存有个整体的概念。最终你会发现强缓存,协商缓存 和 启发式缓存是如此的简单。 ” 导读 浏览器对
CSDN技术头条
2018/02/12
1.4K0
浏览器缓存机制剖析
RFC2616-HTTP1.1-Header Field Definitions(头字段规定部分—译文)
part of Hypertext Transfer Protocol -- HTTP/1.1
zaking
2018/10/12
1.6K0
HTTP权威指南
1.Web服务器是Web资源(Web resource)的宿主,资源可以是静态文件或动态内容
硬核项目经理
2019/08/07
1.4K0
HTTP缓存
HTTP 缓存不是必须的,但重用缓存的资源通常是必要的。它可以减少服务器的压力,如果不使用缓存,每次发起请求都要求服务器发送相应数据,很多时候服务器发来的内容并没有发生变化,就会“浪费”服务器带宽。可以在客户端设置缓存,给缓存加上过期时间,如果期限没到就是用本地缓存的内容。然而常见的 HTTP 缓存只能存储 GET 响应,对于其他类型的响应则无能为力。
多云转晴
2020/06/03
8760
http缓存与离线缓存
一、http协议实现缓存 1. 缓存头部 通用缓存、条件缓存、缓存控制三大类 头部名称 说明 请求/响应 通用缓存头部 控制客户端是否向服务器发送请求或者是服务端响应请求 cache-control 用于随报文传递的缓存提示 pragma http1.0的,等于cache-control:no-cache,pragma优先级高于expires 条件头部 Last-Modified 服务器响应时将文本最后修改时间放在此头部一起传送,如:Last-Modified:
sam dragon
2018/01/17
1.6K0
http缓存与离线缓存
用 cURL 请求测试 ETag 浏览器缓存[每日前端夜话0xCC]
最近,我一直在玩 Netlify (https://www.netlify.com/),结果我对内容交付网络(CDN)常见的缓存策略越来越熟悉。有一种将 ETag标识符用于 Web 资源的策略。
疯狂的技术宅
2019/10/13
1.4K0
相关推荐
[译] HTTP 缓存头部 - 完全指南
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验