HTTP缓存

103 阅读4分钟

一、强缓存(强制缓存)

(一)引入的HTTP版本

  • HTTP/1.0:引入了Expires头字段。
  • HTTP/1.1:引入了Cache-Control头字段,取代了Expires

(二)特点

  1. Expires(HTTP/1.0)

    • 定义Expires是一个绝对时间,用于指定资源的过期时间。

    • 特点

      • 客户端在请求资源时,会检查本地缓存的Expires时间。如果当前时间早于Expires时间,客户端会直接使用本地缓存,而不会向服务器发送请求。
      • 优点是简单直接,但缺点是依赖于客户端和服务器的系统时间同步。如果客户端时间不准确,可能会导致缓存失效或缓存被误用。
    • 示例

      HTTP/1.0 200 OK
      Expires: Wed, 21 Oct 2025 07:28:00 GMT
      
  2. Cache-Control(HTTP/1.1)

    • 定义Cache-Control是一个指令集,用于更灵活地控制缓存行为。其中,max-age是最重要的指令,表示资源的相对过期时间(以秒为单位)。

    • 特点

      • max-age使用相对时间,避免了因客户端和服务器时间不一致导致的问题。
      • 提供了更丰富的指令,如private(仅在客户端缓存)、public(可在任何地方缓存)、no-cache(不使用缓存,但可以存储缓存)、no-store(不存储任何缓存)等。
      • 优先级高于Expires,如果同时存在,Cache-Control会覆盖Expires
    • 示例

      HTTP/1.1 200 OK
      Cache-Control: max-age=3600
      

(三)服务器更新处理

  • 问题:如果服务器上的资源已经更新,但客户端仍然使用本地缓存(因为缓存未过期),会导致客户端看到的不是最新内容。

  • 处理方式

    • 修改资源的URL:这是最常用的方式。例如,将资源的URL从style.css改为style-v2.css,或者在URL中添加版本号或时间戳(如style.css?v=20250416)。这样,客户端会请求新的URL,从而获取到更新后的资源。
    • 缩短缓存时间:将max-age设置为较短的时间(如几分钟),这样可以减少客户端使用过时缓存的可能性,但会增加服务器的请求量。

二、协商缓存(验证缓存)

(一)引入的HTTP版本

  • HTTP/1.0:引入了Last-ModifiedIf-Modified-Since
  • HTTP/1.1:引入了ETagIf-None-Match

(二)特点

  1. Last-ModifiedIf-Modified-Since(HTTP/1.0)

    • 定义

      • Last-Modified:服务器在响应中返回资源的最后修改时间。
      • If-Modified-Since:客户端在请求时,将上次获取的Last-Modified时间发送给服务器,服务器根据该时间判断资源是否发生变化。
    • 特点

      • 如果资源自上次请求后未发生变化,服务器返回304 Not Modified,客户端直接使用本地缓存。
      • 优点是简单,但缺点是只能精确到秒,对于频繁更新的资源(如每秒更新多次)不够精确。
    • 示例

      HTTP/1.0 200 OK
      Last-Modified: Wed, 21 Oct 2025 07:28:00 GMT
      
  2. ETagIf-None-Match(HTTP/1.1)

    • 定义

      • ETag:服务器在响应中返回资源的唯一标识符(通常是文件的哈希值或版本号)。
      • If-None-Match:客户端在请求时,将上次获取的ETag值发送给服务器,服务器通过比较ETag值来判断资源是否发生变化。
    • 特点

      • ETag的精度更高,可以精确到资源的每一个字节,适合频繁更新的资源。
      • Last-Modified相比,ETag可以更好地处理资源的微小变化。
    • 示例

      HTTP/1.1 200 OK
      ETag: "123456789abcdef"
      

(三)服务器更新处理

  • 问题:服务器上的资源更新后,客户端需要能够及时获取到更新后的资源。

  • 处理方式

    • Last-Modified方式

      • 当资源更新时,服务器更新Last-Modified时间。客户端在请求时通过If-Modified-Since发送上次获取的时间,服务器比较后如果发现资源已更新,则返回新的资源和新的Last-Modified时间。
    • ETag方式

      • 当资源更新时,服务器生成新的ETag值。客户端在请求时通过If-None-Match发送上次获取的ETag值,服务器比较后如果发现ETag不匹配,则返回新的资源和新的ETag值。
    • 示例

      • 客户端请求:

        GET /resource HTTP/1.1
        If-None-Match: "123456789abcdef"
        
      • 服务器响应(如果资源未变化):

        HTTP/1.1 304 Not Modified
        
      • 服务器响应(如果资源已变化):

        HTTP/1.1 200 OK
        ETag: "987654321fedcba"
        Content-Type: text/html
        <new resource content>