HTTP中的强缓存与协商缓存

news/2024/9/25 0:13:30

HTTP中的强缓存与协商缓存

强缓存

在浏览器加载资源的时候,首先会根据请求头的expirescache-control判断是否命中强缓存策略,判断是否向远程服务器请求资源还是去本地获取缓存资源。

Expires

Expireshttp1.0的规范,用于表示资源的过期时间的请求头字段,值是一个绝对时间,是由服务器端返回的。

在浏览器第一个请求资源时,服务器端的响应头会附上Expires这个响应字段,当浏览器在下一次请求这个资源时会根据上次的expires字段是否使用缓存资源(当请求时间小于服务端返回的到期时间,直接使用缓存数据)

expires是根据本地时间来判断的,假设客户端和服务器时间不同,会导致缓存命中误差。

Cache-control

上面我们提到了Expires有个缺点,当客户端本地时间被修改时浏览器会直接向服务器请求新的资源,为了解决这个问题,在http1.1规范中,提出了cache-control字段,且这个字段优先级高于上面提到的Expires,值是相对时间。

cache-control中有常见的几个响应属性值,它们分别是

属性值 备注
max-age 3600 例如值为3600,表示(当前时间+3600秒)内不与服务器请求新的数据资源
s-maxage 和max-age一样,但这个是设定代理服务器的缓存时间
private 内容只缓存到私有缓存中(仅客户端可以缓存,代理服务器不可缓存)
public 所有内容都将被缓存(客户端和代理服务器都可缓存)
no-store 不缓存任何数据
no-cache 储存在本地缓存区中,只是在与原始服务器进行新鲜度再验证之前,缓存不能将其提供给客户端使用

协商缓存

上面提到的强缓存都是由本地浏览器在确定是否使用缓存,当浏览器没有命中强缓存时就会向浏览器发送请求,验证协商缓存是否命中,如果缓存命中则返回304状态码,否则返回新的资源数据。

协商缓存(也叫对比缓存)是由服务器来确定资源是否可用,这将涉及到两组字段成对出现的,在浏览器第一次发出请求时会服务器返回的响应会带上字段(Last-Modified或者Etag,则后续请求则会带上对于的对应请求字段(if-modified-since或者if-none-Match),若响应头没有Last-Modified或者Etag,则请求头也不会有对应的字段。

  • Last-modified表示本地文件最后修改时间,由服务器返回。
  • if-modified-since是浏览器在请求数据时带上的字段,值是上次服务器返回的Last-modified。
  • ETag是一个文件的唯一标识符,当资源发生变化时这个ETag就会发生变化。弥补了上面last-modified可能出现文件内容没有变化但是last-modified发生了变化出现重新向服务器请求资源情况。这个值也是又服务器返回的。
  • if-none-match是浏览器请求数据时带上的字段,值是上次服务器返回的ETag

Etag/If-None-Match(标识符字符串) 与 Last-Modified/If-Modified-Since 不同的是,返回 304 时,ETag 还是会重新生成返回至浏览器,Etag的优先级高于Last-Modified

结合强缓存具体请求流程

  1. 当浏览器发起一个资源请求时,浏览器会先判断本地是否有缓存记录,如果没有会向浏览器请求新的资源,并记录服务器返回的last-modified
  2. 如果有缓存记录,先判断强缓存是否存在(cache-control优先于expires,后面会说),如果强缓存的时间没有过期则返回本地缓存资源(状态码为200)
  3. 如果强缓存失效了,客户端会发起请求进行协商缓存策略,首先服务器判断Etag标识符,如果客户端传来标识符和当前服务器上的标识符是一致的,则返回状态码 304 not modified(不会返回资源内容)
  4. 如果没有Etag字段,服务器会对比客户端传过来的if-modified-match,如果这两个值是一致的,此时响应头不会带有last-modified字段(因为资源没有变化,last-modified的值也不会有变化)。客户端304状态码之后读取本地缓存。如果last-modified
  5. 如果Etag和服务器端上的不一致,重新获取新的资源,并进行协商缓存返回数据。

为什么需要ETag

它的出现主要是解决last-modified几个比较难以解决的问题

  1. 在没有修改文件内容情况下文件的最后修改时间可能也会改变,这会导致客户端认为这文件被改动了,从而重新请求
  2. 可能有些文件修改比较频繁,秒级以内修改的,If-Modified-Since 能检查到的粒度是秒级的,使用 Etag 就能够保证这种需求下客户端在 1 秒内能刷新多次。
  3. 有些服务器不能精确获取文件的最后修改时间

状态码区别

  • 200 请求成功,服务器返回全新的数据
  • 200 from memory cache / from disk cache 本地强缓存还在有效期,直接使用本地缓存
  • 304 请求成功,走了协商缓存,服务器判定(EtagLast-modified)没有过期,告知浏览器使用缓存

from memory cache :是页面刷新的时候内存取的。

from disk cache :页面tab关闭后从磁盘取的。

缓存优先级

expirescache-control如果同时存在时,cache-control会覆盖expiresexpires无效,无论是否过期,。即 Cache-control > expires

强缓存和协商缓存如果同时存在时,会去先对比强缓存是否还再有效期,如果强缓存生效则对比协商缓存,即强缓存 > 协商缓存

协商缓存Etaglast-modified同时存在时,会先比较Etaglast-modified无效,即Etag > last-modified

刷新影响

  1. 当ctrl+f5强制刷新时,从服务器加载,跳过强缓存和协商缓存。
  2. 当f5刷新时,跳过强缓存,但是会检查协商缓存

其他补充

  • 协商缓存想要配合强缓存使用,如果不开启强缓存使用,协商缓存没有意义
  • 大部分web服务器默认开启协商缓存,且是同时开启last-modifiedEtag

注意场景

  1. 分布式系统里last-modified需要保持一致,以免负载到不同的机器导致比对失败,从而返回新资源
  2. 分布式系统尽量关闭掉Etag,因为每一台服务器生成的Etag是不同的

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

924 pwn学习

9/24 pwn学习 知道了一次完整的pwn攻击流程,现在我们正式开始学习pwn基础知识 —————————pwn方向以 难入门 难提升著称 基础知识-C语言学习-1 由于pwn要求c语言必须掌握,所以我们先进行一段时间的的C语言学习 学习视频:浙江大学翁恺教你C语言程序设计!C语言基础入门…

Raft总结

Raft算法State所有server都有的持久化状态 先存储,然后响应RPCcurrentTerm 当前任期,初始为0,单调递增votedFor 当前任期投票给谁了,没有就是nulllog[] 日志条目,每个条目都包含命令、Leader收到条目时的任期,第一个条目的index为1所有server都有的Volatile statecommitI…

Lab3 Raft

Lab3 Raft 1.Getting Started 代码位置:基础框架代码位置:src/raft/raft.go测试代码:src/raft/test_test.go建议测试时使用-race 2.The code向raft/raft.go添加代码来实现Raft。实现必须支持以下接口 // 创建一个Raft Server rf := Make(peers, me, persister, applyCh) fun…

Lab3 记录

Part 3A: leader election 1.选举主要流程新服务器加入集群服务器在启动时状态是Follower。只要持续接收到Leader或Candidate的心跳信息,就继续保持Follower状态。开始选举每个Server都有一个随机的选举超时时间,选举超时在一个固定区间内随机选择(例如,150-300毫秒) 如果…

软件工程课程第三次作业

软件工程 https://edu.cnblogs.com/campus/fzu/SE2024作业要求 https://edu.cnblogs.com/campus/fzu/SE2024/homework/13261作业目标 分析学生们的需求,设计一个app原型解决他们的问题学号 072208130合作伙伴 052205144张诗悦使用figma设计原型,原型链接:https://www.figma.…

大文件去重

若文件存的字符如下图,要求进行去重可将数据存入HashSet,如下,但如果文件很大,大于虚拟机内存的话,会报异常java.lang.OutOfMemoryError: Java heap spaceHashSet set = new HashSet();File file = new File("E:\\aa.txt");BufferedReader reader = new Buffere…

9月13日关于数组存储数据

在题目中要求建立数组来存储项目信息,储存的内容包括String、int、boolean、double等各种不同类型,刚开始我还处于建立普通数组要不是int【】要不是string【】,越琢磨越不对劲这样并不能存储不同类型的数据,但是数据又需要统一存取,网上又没有这么简单的讲解,也是被这个简…

9.24日总结

今日上学配置了Node.JS的环境变量,并应用VScode进行JavaScript的相关学习应用 其中