客户端Web资源缓存

embedded/2024/10/22 13:32:22/

为了提高Web服务器的性能,其中的一种可以提高Web服务器性能的方法就是采用缓存技术。

1.缓存

1.1.什么是缓存

如果某个资源的计算耗时或耗资源,则执行一次并存储结果。当有人随后请求该资源时,返回存储的结果,而不是再次计算。

1.2.新鲜度和陈旧度

问题的关键在于“计算”不是数学计算。在数学中,计算的结果随时间而变化。在网络上,您昨天请求的资源可能与您今天请求的资源不同。因此就会有新鲜度和陈旧度两个关键概念。

A fresh response is one whose age has not yet exceeded its freshness lifetime. Conversely, a stale response is one where it has.
A response’s freshness lifetime is the length of time between its generation by the origin server and its expiration time. An explicit expiration time is the time at which the origin server intends that a stored response can no longer be used by a Cache without further validation, whereas a heuristic expiration time is assigned by a Cache when no explicit expiration time is available. A response’s age is the time that has passed since it was generated by, or successfully validated with, the origin server.
When a response is “fresh” in the cache, it can be used to satisfy subsequent requests without contacting the origin server, thereby improving efficiency.
— RFC 7234 - 4.2. Freshness

2.如何进行客户端Web资源缓存?

2.1.以前的方法

万维网刚开始时相对简单。客户端会发送请求,服务器会返回所请求的资源。当资源是页面时,它是静态页面还是服务器呈现的页面并不重要。因此,早期的客户端缓存相当简单。

2.2.现在的方法

2.2.1.Web资源缓存规范

Web 缓存的第一个规范于 2014 年在RFC 7234(又名HTTP/1.1 缓存)中定义。请注意,自 2022 年起,它已被RFC 9111取代。

2.2.2.具体的方法

HTTP__24">2.2.2.1.Pragma HTTP 标头

已经弃用

HTTP__28">2.2.2.2.Expire HTTP 响应标头

最直接的缓存管理是通过Expire响应标头。当服务器返回资源时,它会指定缓存在哪个时间戳之后过期。请求缓存资源时,浏览器有两个选项:

  • 当前时间在到期时间戳之前:资源被视为新鲜,浏览器从本地缓存中提供该资源
  • 或者是之后:资源被视为过时,并且浏览器需要从服务器获取资源,因为它未被缓存
2.2.2.2.1.优点

它完全是本地决策。它不需要向服务器发送请求

2.2.2.2.2.不足
  • 是否使用本地缓存资源的决定是基于启发式的。尽管值Expiry是未来的,但资源可能已在服务器端发生变化,因此浏览器会提供过期的资源。相反,浏览器可能会因为时间已到而发送请求,但资源尚未发生变化。

  • Expire这非常基本。资源要么是新鲜的,要么是陈旧的;要么从中返回,Cache要么再次发送请求,控制的维度有限。

2.2.2.3.Cache-Control

Cache-Control的目标:

  • 绝不缓存资源
  • 在提供资源之前,验证是否应从缓存中提供资源
  • 中间缓存(代理)可以缓存资源吗?
    Cache-Control的基本实现流程:

在这里插入图片描述
由于Cache-Control和Expire一样都是客户端本地的,具体来说就是如果需要,浏览器会从其缓存中提供资源,而无需向服务器发出任何请求。

2.2.2.4.Last-Modified 和 ETag

为了避免提供过期资源的风险,浏览器必须向服务器发送请求。输入Last-Modified响应标头。 If-Modified-Since与请求Last-Modified标头配合使用:

The If-Modified-Since request HTTP header makes the request conditional: the server sends back the requested resource, with a 200 status, only if it has been last modified after the given date. If the resource has not been modified since, the response is a 304 without any body; the Last-Modified response header of a previous request contains the date of last modification. Unlike If-Unmodified-Since, If-Modified-Since can only be used with a GET or HEAD.
在这里插入图片描述

注意:
具有和其他非幂等方法If-Unmodified-Since的相反功能:它返回HTTP 错误,以避免覆盖已更改的资源。POST412 Precondition Failed。

分布式系统中时间戳的问题在于无法保证系统中的所有时钟都具有相同的时间。时钟以不同的速度漂移,需要定期同步Last-Modified到同一时间。因此,如果生成标头的服务器和接收标头的服务器If-Modified-Since不同,则结果可能会因它们的漂移而出乎意料。请注意,这也适用于标Expire头。

Etags 是时间戳的替代方案,可避免上述问题。服务器计算所提供资源的哈希值,并将ETag包含该值的标头与资源一起发送。当新请求包含If-None-Match哈希值时,服务器会将其与当前哈希值进行比较。如果它们匹配,则返回304如上所述的哈希值。

与仅提供时间戳相比,计算哈希值的开销较小,但现在被认为是一种很好的做法。

2.2.2.5.缓存 API

客户端最新的缓存方式是通过Cache API。它提供了一个通用的缓存接口:你可以将其视为浏览器提供的本地键值。

缓存 API提供以下方法:

  • Cache.match(request, options)

返回Promise解析与对象中第一个匹配的请求相关的响应Cache。

  • Cache.matchAll(request, options)

返回Promise解析为对象中所有匹配响应的数组Cache。

  • Cache.add(request)

获取 URL,检索它并将生成的响应对象添加到给定的缓存中。这在功能上等同于调用fetch(),然后使用put()将结果添加到缓存中。

  • Cache.addAll(requests)

获取 URL 数组,检索它们,并将生成的响应对象添加到给定的缓存中。

  • Cache.put(request, response)

接受请求及其响应并将其添加到给定的缓存中。

  • Cache.delete(request, options)

查找Cache以请求为键的条目,如果找到匹配的条目并将其删除,则返回Promise解析为的条目。如果未找到任何条目,则解析为。trueCacheCachePromisefalse

  • Cache.keys(request, options)

返回Promise解析为键数组的Cache。

Cache API 与Service Workers配合使用。流程很简单:

首先在 URL 上注册一个 Service Worker,浏览器在 URL 获取调用之前调用该 worker,从 worker 中,你可以从缓存中返回资源,并避免向服务器发出任何请求,它允许我们在初始加载后将资源放入缓存中,以便客户端可以离线工作 ,而具体效果取决于用例。


http://www.ppmy.cn/embedded/42316.html

相关文章

【学习】实验室服务器常用的Linux指令。

1. 下载GitHub代码。 使用代码: git clone https://github.com/Turoad/CLRNet.git2. 压缩 / 解压。 打包压缩 是日常工作中备份文件的一种方式 在不同操作系统中,常用的打包压缩方式是不同的选项 含义 Windows 常用 rarMac 常用 zipLinux 常用 tar.gz…

解决SpringBoot使用@Transactional进行RestTemplate远程调用导致查询数据记录为null的bug

开启事务过程中,如果远程调用查询当前已经开启但没有提交的事务,就会查不到数据。 示例代码 import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.transaction.annotation.Transactional; import o…

如何搭建一个vue项目(完整步骤)

搭建一个新的vue项目 一、安装node环境二、搭建vue项目环境1、全局安装vue-cli2、进入你的项目目录,创建一个基于 webpack 模板的新项目3、进入项目:cd vue-demo,安装依赖4、npm run dev,启动项目 三、vue项目目录讲解四、开始我们…

功耗相关总结

文章目录 功耗相关的使用场景MCU中低功耗的应用RTOS中低功耗应用 功耗相关的使用场景 目前越来越多的嵌入式设备采用电池进行供电,而不是跟台式电脑一样,可以一直连接着电源。在电池供电的场景下,对功耗的要求很高,工程师们尽量希…

Web3 ETF 软件开发流程

开发 Web3 ETF 软件涉及多个阶段和流程,以下是一个可能的开发流程。这是一个简化的开发流程,实际开发过程中可能会根据具体情况进行调整和补充。在每个阶段都要注重沟通、团队协作和持续改进,以确保项目的顺利进行和成功交付。北京木奇移动技…

MySQL之Schema与数据类型优化(四)

Schema与数据类型优化 日期和时间类型 MySQL可以使用许多类型来保存日期和时间值,例如YEAR和DATE.MySQL能存储的最小时间粒度为秒(MariaDB支持微秒级别的时间类型)。但是MySQL也可以使用微秒级别的粒度进行临时运算,接下来会展示如何绕开这种存储限制。…

Llama 3 模型家族构建安全可信赖企业级AI应用之code shield(三)Code Shield代码示例

LlaMA 3 系列博客 基于 LlaMA 3 LangGraph 在windows本地部署大模型 (一) 基于 LlaMA 3 LangGraph 在windows本地部署大模型 (二) 基于 LlaMA 3 LangGraph 在windows本地部署大模型 (三) 基于 LlaMA…

平均工资数据分析之回归

链接: R语言实战——中国职工平均工资的变化分析——相关与回归分析 1、模型诊断和评估的方法 1. 残差分析 1、残差图 (Residual Plot):用于检查残差是否存在非随机模式。理想情况下,残差应随机分布在零附近。 2、Q-Q 图 (Quantile-Quantile Plot)&am…