HTTP中的强缓存与协商缓存

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是不同的
posted @ 2024-09-25 00:12  CD、小月  阅读(33)  评论(0编辑  收藏  举报