http缓存

183 阅读7分钟

什么是 HTTP Cache

当我们访问一个网站时,会加载各种资源,如 HTML文档、JS、CSS、图片等。浏览器会将一些不经常变的资源保存在本地,这样下次访问相同网站时,就直接从本地加载资源,并不通过请求服务器,这就是浏览器缓存。

HTTP 缓存机制就是,配置服务器响应头来告诉浏览器是否应该缓存资源、是否强制校验缓存、缓存多长时间;浏览器非首次请求根据响应头是否应该取缓存、缓存过期发送请求头验证缓存是否可用还是重新获取资源的过程。

缓存的分类

根据是否需向服务器发起HTTP请求,将缓存过程划分为两个部分:
强制缓存和协商缓存,强缓优先于协商缓存。

  • 强缓存,服务器通知浏览器一个缓存时间,在缓存时间内,下次请求,直接用缓存,不在时间内,执行比较缓存策略。
  • 协商缓存,让客户端与服务器之间能实现缓存文件是否更新的验证、提升缓存的复用率,将缓存信息中的Etag和Last-Modified通过请求发送给服务器,由服务器校验,返回304状态码时,浏览器直接使用缓存。

HTTP缓存都是从第二次请求开始的:

  • 第一次请求资源时,服务器返回资源,并在response header中回传资源的缓存策略;
  • 第二次请求时,浏览器判断这些请求参数,击中强缓存就直接200,否则就把请求参数加到request header头中传给服务器,看是否击中协商缓存,击中则返回304,否则服务器会返回新的资源。这是缓存运作的一个整体流程图:

     ![]( "研发中心Engineer > 浏览器缓存 > image2023-8-28_11-4-38.png")

强缓存

强缓存的意思很简单,直接从浏览器缓存过的本地进行读取,不会去请求服务器。例如请求一个图片,当缓存后,第二次访问,直接从本地去拿,不会再去请求这个资源,可以节省服务器资源。

在 chrome 控制台的 network 选项中可以看到该请求返回 200 的状态码,并且size显示from disk cachefrom memory cache

![]( "研发中心Engineer > 浏览器缓存 > image2023-8-28_11-29-12.png")

![]( "研发中心Engineer > 浏览器缓存 > image2023-8-28_11-30-18.png")

Expires

Expires 响应头,它是 HTTP/1.0 的产物。代表该资源的过期时间,其值为一个绝对时间。它告诉浏览器在过期时间之前可以直接从浏览器缓存中存取数据。由于是个绝对时间,客户端与服务端的时间时差或误差等因素可能造成客户端与服务端的时间不一致,将导致缓存命中的误差。如果在Cache-Control响应头设置了 max-age 或者 s-max-age 指令,那么 Expires 会被忽略。

Expires: Wed, 21 Oct 2023 07:28:00 GMT

Cache-Control

Cache-Control 出现于 HTTP/1.1。可以通过指定多个指令来实现缓存机制。主要用表示资源缓存的最大有效时间。即在该时间端内,客户端不需要向服务器发送请求。优先级高于 Expires。其过期时间指令的值是相对时间,它解决了绝对时间的带来的问题。

Cache-Control: max-age=315360000

Cache-Control 有很多属性,不同的属性代表的意义也不同。

可缓存性

  • public 表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存。
  • private 表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)
  • no-cache 不使用强缓存,需要与服务器验协商缓存验证。
  • no-store 缓存不应存储有关客户端请求或服务器响应的任何内容,即不使用任何缓存。

过期

  • max-age=<seconds> 缓存存储的最大周期,超过这个周期被认为过期。
  • s-maxage=<seconds> 设置共享缓存。会覆盖max-ageexpires,私有缓存会忽略它
  • max-stale[=<seconds>] 客户端愿意接收一个已经过期的资源,可以设置一个可选的秒数,表示响应不能已经过时超过该给定的时间。
  • min-fresh=<seconds> 客户端希望在指定的时间内获取最新的响应

重新验证和重新加载

  • must-revalidate 如页面过期,则去服务器进行获取。
  • proxy-revalidatemust-revalidate 作用相同,但是用于共享缓存。

其他

  • only-if-cached 不进行网络请求,完全只使用缓存。
  • no-transform 不得对资源进行转换和转变。例如,不得对图像格式进行转换。

协商缓存

协商缓存会先向服务器发送一个请求,服务器会根据这个请求的 request header 的一些参数来判断是否命中协商缓存,如果命中,则返回 304 状态码并带上新的 response header 通知浏览器从缓存中读取资源。

![]( "研发中心Engineer > 浏览器缓存 > image2023-8-28_11-50-42.png")

Last-Modified、If-Modified-Since

Last-ModifiedIf-Modified-Since 的值都是 GMT 格式的时间字符串,代表的是文件的最后修改时间。

  1. 在服务器在响应请求时,会通过Last-Modified告诉浏览器资源的最后修改时间。
  2. 浏览器再次请求服务器的时候,请求头会包含Last-Modified字段,后面跟着在缓存中获得的最后修改时间。
  3. 服务端收到此请求头发现有if-Modified-Since,则与被请求资源的最后修改时间进行对比,如果一致则返回 304 和响应报文头,浏览器只需要从缓存中获取信息即可。如果已经修改,那么开始传输响应一个整体,服务器返回:200 OK

但是在服务器上经常会出现这种情况,一个资源被修改了,但其实际内容根本没发生改变,会因为Last-Modified时间匹配不上而返回了整个实体给客户端(即使客户端缓存里有个一模一样的资源)。为了解决这个问题,HTTP/1.1 推出了Etag。Etag 优先级高与Last-Modified

Etag、If-None-Match

Etag都是服务器为每份资源生成的唯一标识,就像一个指纹,资源变化都会导致 ETag 变化,跟最后修改时间没有关系,ETag可以保证每一个资源是唯一的。

在浏览器发起请求,浏览器的请求报文头会包含 If-None-Match 字段,其值为上次返回的Etag发送给服务器,服务器接收到次报文后发现 If-None-Match 则与被请求资源的唯一标识进行对比。如果相同说明资源没有修改,则响应返 304,浏览器直接从缓存中获取数据信息。如果不同则说明资源被改动过,则响应整个资源内容,返回状态码 200。

浏览器缓存的优缺点

优点

  • 使用浏览器客户端缓存能够减少请求的时间,提高用户体检,提高页面响应时间。
  • 在前端优化的手段当中,减少http请求的方式,也是其中一种,有效使用缓存,可以减少服务器的压力,提升网站的性能。

缺点

  • 正如字面意思,缓存,就意味着使用缓存的时候,服务器的资源有可能不是最新版本,这就需要在使用的时候,控制缓存的资源和时间,包括常见的CDN手段。

总结

  • HTTP 缓存主要分:强缓存和协商缓存
  • 强制缓存由 Cache-ControlExipres(HTTP1.0)控制。浏览器直接读本地缓存,不会再跟服务器端交互,状态码 200。
  • 协商缓存由 Last-Modified / IfModified-SinceEtag /If-None-Match实现,每次请求需要让服务器判断一下资源是否更新过,从而决定浏览器是否使用缓存,如果是,则返回 304,否则重新完整响应。