http缓存

204 阅读10分钟

一、双缓存的工作机制和使用场景

1. 强制缓存

强制缓存是指浏览器不与服务器进行任何通信,直接使用本地缓存的资源。当资源还在有效期内时,浏览器不会向服务器发送请求,直接从缓存中读取数据。强制缓存的控制通常通过HTTP头信息来实现,例如 ExpiresCache-Control

1.1 主要字段

  • Expires
    Expires 是一个HTTP响应头,它表示资源的过期时间。浏览器在过期时间之前,都会直接使用缓存。如果当前时间超过了 Expires 指定的时间,缓存失效。

    Expires: Wed, 21 Oct 2023 07:28:00 GMT
    
  • Cache-Control
    Cache-Control 是HTTP/1.1中引入的更为灵活的头部字段,可以指定缓存的多种行为。常见的指令包括:

    • max-age:表示资源的有效期,单位是秒。
    • public:资源可以被任何缓存(浏览器、代理服务器等)缓存。
    • private:资源只能被浏览器缓存,代理服务器不能缓存。
    • no-cache:强制客户端发送请求到服务器进行缓存验证。
    • no-store:完全不进行缓存。
    Cache-Control: max-age=3600, public
    

1.2 工作原理

当浏览器请求一个资源时,服务器会在响应头中加入 ExpiresCache-Control。浏览器根据这些头部信息决定是否可以直接使用缓存。如果缓存有效,浏览器不会再次请求服务器。

1.3 特点

  • 浏览器不与服务器通信,直接使用本地缓存。
  • 通过 ExpiresCache-Control 控制缓存时间。
  • 若资源未过期,即使服务器上的资源已更新,浏览器也不会知道。

2. 协商缓存

协商缓存是指浏览器在使用缓存之前,会先与服务器确认缓存资源是否仍然有效。如果资源没有变化,服务器会返回304状态码,告知浏览器可以使用本地缓存。如果资源已变化,服务器会返回新的资源。协商缓存主要通过 Last-ModifiedIf-Modified-SinceETagIf-None-Match 头部字段实现。

2.1 主要字段

  • Last-ModifiedIf-Modified-Since

    • Last-Modified 表示资源最后修改的时间。
    • If-Modified-Since 是浏览器下次请求资源时,携带的上次资源最后修改时间,服务器根据这个时间判断资源是否发生了变化。
    Last-Modified: Wed, 21 Oct 2022 07:28:00 GMT
    
  • ETagIf-None-Match

    • ETag 是一个资源的唯一标识符(通常是文件内容的哈希值)。
    • If-None-Match 是浏览器下次请求资源时,携带的上次资源的 ETag,服务器根据这个标识符判断资源是否发生了变化。
    ETag: "34ac87a3"
    

2.2 工作原理

  1. 第一次请求资源时,服务器会在响应头中加入 Last-ModifiedETag
  2. 浏览器下一次请求该资源时,会在请求头中带上 If-Modified-SinceIf-None-Match
  3. 服务器收到请求后,比较资源的修改时间和 ETag,如果资源未修改,返回304状态码,浏览器使用缓存。如果资源已修改,返回新的资源。

2.3 特点

  • 浏览器与服务器通信,确认缓存是否有效。
  • 通过 Last-Modified/If-Modified-SinceETag/If-None-Match 实现。
  • 即使资源未修改,仍然会有HTTP请求,但返回的是304状态码,不返回资源内容。

3. 强制缓存和协商缓存的区别

对比项强制缓存协商缓存
是否与服务器通信
主要控制头Expires, Cache-ControlLast-Modified, ETag
缓存有效时状态码200 (from cache)304 (Not Modified)
缓存过期后行为重新请求服务器重新请求服务器
适用场景资源长期不变的静态资源资源可能频繁更新的动态资源

4. 实际应用

在实际开发中,通常会结合使用强制缓存和协商缓存:

  • 对于静态资源(如图片、CSS、JavaScript),使用强制缓存,设置较长的过期时间(例如一年)。
  • 对于动态资源(如HTML页面),使用协商缓存,确保资源更新时客户端能够及时获取最新内容。

要确定缓存的有效期,主要是通过分析服务器响应头中的相关字段来实现的。浏览器根据这些字段来决定是否可以直接使用缓存,或者需要与服务器进行协商确认缓存是否仍然有效。

二、如何查看缓存的有效期

要查看一个资源的缓存有效期,可以通过浏览器的开发者工具(通常是 "Network" 面板)来查看请求和响应头。以下是在不同浏览器中查看缓存有效期的步骤:

1. Chrome 浏览器

  1. 打开 Chrome 浏览器并加载网页。
  2. F12 或右键点击页面,选择 "检查" 以打开开发者工具。
  3. 点击 "Network"(网络)选项卡。
  4. 重新加载页面(可以按 Ctrl + RCmd + R)。
  5. 点击一个资源(例如一个图片、CSS文件或JavaScript文件)以查看其请求和响应头。
  6. 在右侧的 "Headers"(头部)面板中,查看响应头中的 Cache-ControlExpires 字段。

2. Firefox 浏览器

  1. 打开 Firefox 浏览器并加载网页。
  2. F12 或右键点击页面,选择 "检查元素" 以打开开发者工具。
  3. 点击 "Network"(网络)选项卡。
  4. 重新加载页面。
  5. 点击一个资源,在右侧的 "Headers"(头部)面板中查看 Cache-ControlExpires 字段。

3. Edge 浏览器

  1. 打开 Edge 浏览器并加载网页。
  2. F12 或右键点击页面,选择 "检查元素" 以打开开发者工具。
  3. 点击 "Network"(网络)选项卡。
  4. 重新加载页面。
  5. 点击一个资源,在右侧的 "Headers"(头部)面板中查看 Cache-ControlExpires 字段。

缓存有效期的计算

  • 对于 Expires,直接比较当前时间与响应头中的过期时间即可。
  • 对于 Cache-Control: max-age,有效期的计算方式是:请求时间 + max-age 的值。

示例: 假设当前时间是 2023-10-21 07:00:00 GMT,服务器返回的响应头如下:

Cache-Control: max-age=3600

那么缓存的有效期就是 2023-10-21 08:00:00 GMT

缓存验证(协商缓存)

如果缓存已经过期,浏览器会使用协商缓存机制与服务器进行验证。协商缓存通过 Last-Modified/If-Modified-SinceETag/If-None-Match 来实现。即使缓存过期,如果资源未发生变化,服务器会返回 304 Not Modified,浏览器仍然可以使用缓存。

三. ETagLast-Modified的优先级

在HTTP缓存机制中,ETagLast-Modified 都是用于协商缓存的响应头部字段,它们允许浏览器和服务器之间进行缓存验证,以确定缓存的资源是否仍然有效。但是,ETag 的优先级高于 Last-Modified,当两者同时存在时,服务器会优先使用 ETag 进行缓存验证。

1. 工作原理

1.1 Last-Modified

  • 定义Last-Modified 是一个HTTP响应头部,表示资源的最后修改时间。它是一个GMT时间值,例如 Mon, 10 Nov 2023 10:00:00 GMT
  • 工作机制
    • 当浏览器第一次请求资源时,服务器会在响应头中返回 Last-Modified,表示该资源最后一次修改的时间。
    • 在后续请求中,浏览器会通过 If-Modified-Since 请求头将这个时间发送回服务器,服务器会比较这个时间与资源的实际修改时间,以判断资源是否发生了变化。
      • 如果资源未变化,服务器返回 304 Not Modified
      • 如果资源已变化,服务器返回新的资源和 200 OK

1.2 ETag

  • 定义ETag 是一个HTTP响应头部,表示资源的唯一标识符。通常,这个标识符是基于资源内容生成的哈希值或版本号。
  • 工作机制
    • 当浏览器第一次请求资源时,服务器会在响应头中返回 ETag,表示该资源的唯一标识。
    • 在后续请求中,浏览器会通过 If-None-Match 请求头将这个 ETag 发送回服务器,服务器会比较客户端发送的 ETag 与当前资源的 ETag,以判断资源是否发生了变化。
      • 如果资源未变化,服务器返回 304 Not Modified
      • 如果资源已变化,服务器返回新的资源和 200 OK

2. 优先级

ETag 的优先级高于 Last-Modified。当服务器同时返回 ETagLast-Modified 时,浏览器会优先使用 ETag 进行缓存验证。具体原因如下:

  1. 精确度ETag 是基于资源内容的哈希值或版本号,能够精确地标识资源的变动,即使资源在一秒之内多次修改,ETag 也能正确反映这种变化。而 Last-Modified 只能精确到秒级,如果资源在同一秒内发生多次修改,Last-Modified 可能无法正确标识这些变化。

  2. 一致性ETag 提供了更一致的验证机制,尤其是在分布式系统或多服务器环境中,不同服务器上的文件修改时间可能不一致,但 ETag 可以确保资源的唯一标识。

  3. HTTP规范:根据HTTP规范和实际应用,当 ETag 存在时,服务器应优先使用 ETag 进行缓存验证,而忽略 Last-Modified

3. 工作流程

3.1 只有 Last-Modified

  1. 第一次请求

    GET /resource HTTP/1.1
    

    响应

    HTTP/1.1 200 OK
    Last-Modified: Mon, 10 Nov 2023 10:00:00 GMT
    Content-Type: text/html
    
  2. 第二次请求(缓存过期或需要验证):

    GET /resource HTTP/1.1
    If-Modified-Since: Mon, 10 Nov 2023 10:00:00 GMT
    

    服务器验证

    • 如果资源未变化,返回 304 Not Modified
    • 如果资源已变化,返回新的资源和 200 OK

3.2 同时有 ETag 和 Last-Modified

  1. 第一次请求

    GET /resource HTTP/1.1
    

    响应

    HTTP/1.1 200 OK
    ETag: "34ac87a3"
    Last-Modified: Mon, 10 Nov 2023 10:00:00 GMT
    Content-Type: text/html
    
  2. 第二次请求(缓存过期或需要验证):

    GET /resource HTTP/1.1
    If-None-Match: "34ac87a3"
    

    服务器验证

    • 服务器优先检查 If-None-Match,并将其与当前资源的 ETag 进行比较。
      • 如果匹配(资源未变化),返回 304 Not Modified
      • 如果不匹配(资源已变化),返回新的资源和 200 OK
    • 服务器不会检查 If-Modified-Since,因为 ETag 优先级更高。

4. 示例

4.1 请求头(浏览器发送的请求,带有 If-None-Match):

GET /resource HTTP/1.1
If-None-Match: "34ac87a3"

4.2 响应头(服务器返回 304 Not Modified):

HTTP/1.1 304 Not Modified
ETag: "34ac87a3"

在这种情况下,服务器返回 304 Not Modified,浏览器可以使用本地缓存中的资源,Last-Modified 不会被用于验证。

总结

  • 优先级ETag 的优先级高于 Last-Modified。当两者同时存在时,服务器会优先使用 ETag 进行缓存验证,而忽略 Last-Modified
  • 精确度ETag 提供了更精确的资源验证机制,因为它基于资源内容的哈希值或版本号,而 Last-Modified 只能精确到秒级。
  • 一致性:在分布式系统或多服务器环境中,ETag 提供了更一致的验证机制。

通过这种方式,ETagLast-Modified 共同提供了灵活且高效的缓存验证机制,减少了不必要的资源传输,提高了性能。但在同时使用时,ETag 具有更高的优先级。

今天就先码到这儿吧!!!