6

HTTP缓存看这一篇就够了

 2 years ago
source link: https://www.51cto.com/article/746168.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

HTTP缓存机制是优化web性能的重要手段,也是优化用户体验的重要一环。了解和熟悉HTTP缓存机制也成为了前端工作者必不可少的技能。

HTTP缓存是用于临时存储网页资源(如HTML页面、图像等),以减少服务器延迟的一种技术。HTTP缓存系统会保存下通过这套系统的文档的副本;如果满足某些条件,则可以由缓存满足后续请求。HTTP缓存系统既可以指设备,也可以指计算机程序。

一、HTTP缓存的类别

HTTP缓存可分为强制缓存和协商缓存。

强制缓存:直接使用客户端缓存,不从服务器拉取新资源,也不验证缓存资源是否过期。返回的状态码为200(OK)。

协商缓存:通过服务器验证资源有效性,资源有效则返回304(Not Modified),资源失效则返回最新的资源文件。

HTTP主流的有三个版本:HTTP/1.0、HTTP/1.1、HTTP/2.0。其中HTTP/1.0和HTTP/1.1的应用最为广泛。HTTP/2.0因对缓存机制的改动有别于HTTP/1.0和HTTP/1.1,因此HTTP/2.0相关内容会在文末总结部分进行介绍。HTTP/1.0与HTTP/1.1可根据缓存类别区分如下:

HTTP版本

HTTP/1.0

Expires

Last-Modified

HTTP/1.1

Cache-Control

二、主流的HTTP缓存参数

2.1 强制缓存

2.1.1 HTTP/1.0 - Expires

Expires​的值为服务端返回的到期时间,是一个GMT​(格林尼治标准时间)绝对时间,如:Tue, 17 Jan 2023 03:48:45 GMT​。下一次请求时,客户端判断当前系统GMT​时间是否小于缓存携带的GMT时间。若小于,直接使用缓存数据,否则从服务器请求新的文件。

图片

不过Expires存在的问题也显而易见。

首先,使用客户端获取的GMT​时间与服务器GMT时间作比较,如果客户端主动修改了系统时间,就会出现缓存命中的误差。

其次,GMT时间是基于格林尼治天文台测算时间后,每隔一小时想全世界发放调时信息。观测本身存在的误差以及非实时的同步机制,都可能会导致出现缓存命中的误差。

所以在HTTP/1.1版本中,使用Cache-Control​中的max-age替代。

2.1.2 HTTP/1.1 - Cache-Control

Cache-Control 是HTTP/1.1中重要的缓存规则。它可以在HTTP请求头和响应头中使用,提供了多样化的配置参数。同时也可以适用于更广泛的复杂场景。

指令格式具有以下有效规则:

  • 不区分大小写,但建议使用小写。
  • 多个指令以逗号分隔。
  • 具有可选参数,可以用令牌或者带引号的字符串语法。

常用的指令如下:

  • no-store:不使用任何形式的缓存。具有HTTP缓存的最高优先级。

图片
  • no-cache:不使用强制缓存。每次进行响应前都向服务器进行缓存有效性验证。

图片
  • public:公共缓存。任何从源服务器到客户端中的每个节点都可以对资源进行缓存。
  • private:私有缓存。仅客户端可以对资源进行缓存。
  • max-age:客户端缓存存储的最长时间,单位秒。判断的优先级高于Expires​,客户端会判断资源已缓存的时长是否小于设置的max-age​时长。是则直接使用缓存数据,否则会进行Expires的判断流程。

图片
  • s-maxage:代理缓存服务器最长的缓存时间,单位秒。优先级高于max-age和Expires,仅适用于缓存服务器。

2.2 协商缓存

客户端缓存失效后会向服务器进行进行缓存有效性验证,这个缓存有效性验证的过程就是协商缓存​。若资源有效,则返回304(Not Modified)​。客户端拿到304状态码后会再从本地缓存中获取资源。整个请求响应过程是与无缓存流程一样的。相对于无缓存流程的优势在于仅响应状态码后,客户端直接从本地缓存获取文件,而无需进行文件下载。减少了网络响应的文件大小,进而加快了网络响应速度。

协商缓存的请求和响应是需要相互配合的,可组合使用。如下表:

版本/阶段

HTTP/1.0

If-Modified-Since/If-Unmodified-Since

Last-Modified

HTTP/1.1

If-None-Match/If-Match

协商缓存会先判断请求头中是否携带no-store。如果携带,则直接返回最新的服务器文件。

图片

2.2.1 HTTP/1.0 - Last-Modified

客户端第一次向服务器请求资源时,服务器会返回资源。同时会在响应头中添加Last-Modified​字段来表明资源的最后修改时间。当客户端强制缓存失效后,会重新向服务器进行缓存有效性验证。在验证的请求头中,会添加If-Modified-Since​字段。服务器会对请求头中的If-Modified-Since​和其存储的资源Last-Modified​进行比较。若If-Modified-Since​的时间不小于Last-Modified​,则资源有效,返回304(Not Modified)​。否则返回资源本身,并且重新记录文件的Last-Modified。

Last-Modified​:响应头携带的资源最后修改时间。格式为last-modified:GMT。

如:last-modified: Sat, 14 Jan 2023 08:40:00 GMT

If-Modified-Since​:请求头携带的资源是否在某个时间后有修改。服务器会使用此值和其本身存储的时间进行比较。格式为:If-Modified-Since:GMT​。只可以用在 GET​ 或 HEAD请求中。

If-Unmodified-Since​:请求头携带的资源是否在某个时间后没有修改。格式为:if-unmodified-since:GMT​ 。有别于If-Modified-Since,If-Unmodified-Since​被用于POST​或其他非简单请求。如果在If-Unmodified-Since​指定的时间内有过修改,则返回412(Precondition Failed)。

图片

Last-Modified也是存在严重问题的。

首先,Last-Modified只关注文件的最后修改时间,和文件内容无关。所以文件内容在修改后又重新恢复,也会导致文件的最后修改时间改变。此时客户端的请求则无法使用缓存。

其次,Last-Modified​只能监听到秒级别的文件修改,如果文件在1秒内进行了多次修改,那么响应头返回的Last-Modified​的时间是不变的。此时客户端因接收到响应304,会导致资源无法及时更新,使用缓存的资源文件。

因此HTTP/1.1使用了ETag来进行缓存协商。

2.2.1 HTTP/1.1 - ETag

为了解决上述Last-Modified​可能存在的不准确的问题,HTTP/1.1推出了新的响应字段ETag​来进行协商缓存。ETag​的优先级比Last-Modified高。

服务器接收到浏览器请求后,会先进行If-None-Match与ETag​值的比较。若相等,则资源有效,返回304(Not Modified)​。否则返回资源本身,并且重新记录文件的ETag。

ETag​:响应头携带的资源标识符。格式为ETag:ETag-value可由服务器自行设置算法生成,通常是使用内容的散列或简单的使用版本号。

如:etag: "I82YRPyDtSi45r0Ps/eo8GbnDfg="

If-None-Match​:请求头携带的是否无匹配文件字段。优先级高于Last-Modified​。当服务器没有任何资源的ETag​与请求头携带的ETag值完全一样时,返回最新的资源,否则服务器会返回304。

如: if-none-match:"I82YRPyDtSi45r0Ps/eo8GbnDfg="

If-Match​:请求头携带的是否存在匹配文件字段。对于简单请求需要搭配 Range​首部使用。对于非简单请求,如PUT​,可用于上传ETag。

如: if-match:"I82YRPyDtSi45r0Ps/eo8GbnDfg="

图片

通过前文,我们了解到 HTTP 缓存主要分:强制缓存、协商缓存。强制缓存由Exipres(HTTP/1.0)、 Cache-Control(HTTP/1.1)控制。客户端直接读本地缓存,不会再跟服务器端交互,状态码 200。

协商缓存由 Last-Modified / If-Modified-Since(HTTP/1.0), Etag /If-None-Match(HTTP/1.1)进行有效性验证,每次请求需要让服务器判断一下资源是否更新过,从而决定客户端是否使用缓存,如果是,则返回 304,否则返回最新文件。

HTTP/2.0中设计了新的缓存方式,服务器推送(Push Server)。有别于强制缓存和协商缓存,属于推送缓存。这种新的缓存方式主要是为了解决客户端缓存时效性的问题,即还没有收到客户端的请求,服务器就把各种资源推送给客户端。比如,客户端只请求了a.html,但是服务器把a.html、a.css、a.png全部发送给客户端。这样的话,只需要一次请求,客户端就更新了所有文件的缓存,提高了缓存的时效性。

GMT(维基百科):https://en.wikipedia.org/wiki/Greenwich_Mean_Time

HTTP缓存(MDN):https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Caching

图片

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK