http 缓存

127 阅读7分钟

HTTP 缓存机制概述

HTTP 缓存机制通过在客户端或代理服务器上存储响应数据,以减少网络延迟和服务器负载,从而加快网页加载速度。缓存机制主要涉及两个策略:强缓存和协商缓存。

强缓存

强缓存是指客户端在缓存有效期内直接使用缓存的数据,而不向服务器发送请求。

协商缓存

协商缓存是指客户端每次请求资源时,都会向服务器发送验证请求,以确认缓存的数据是否仍然有效。如果有效,则服务器返回 304(Not Modified),客户端继续使用缓存数据;否则,服务器返回新的资源数据。

客户端与服务端的交互过程

1. 初次请求

当客户端(如浏览器)首次请求某个资源时,服务器会返回资源数据及缓存相关的头部信息:

请求

GET /resource HTTP/1.1
Host: www.example.com

响应

HTTP/1.1 200 OK
Date: Mon, 08 Jun 2024 10:00:00 GMT
Cache-Control: max-age=3600, must-revalidate
Last-Modified: Wed, 21 Oct 2020 07:28:00 GMT
ETag: "686897696a7c876b7e"
Content-Type: text/html
Content-Length: 1234

<html>...</html>

在这个响应中:

  • Cache-Control: max-age=3600 指示资源可以被缓存 3600 秒(1 小时)。
  • Last-ModifiedETag 提供了资源的最后修改时间和实体标签,用于后续的协商缓存请求。

2. 强缓存

在缓存有效期内(1 小时内),客户端再次请求相同资源时,会直接从缓存中获取数据,而不会向服务器发送请求。

请求

(客户端从缓存中读取,无需与服务器交互)

3. 协商缓存

当缓存过期后,客户端再次请求相同资源时,会向服务器发送验证请求,检查缓存数据是否仍然有效。

请求

GET /resource HTTP/1.1
Host: www.example.com
If-Modified-Since: Wed, 21 Oct 2020 07:28:00 GMT
If-None-Match: "686897696a7c876b7e"

在这个请求中:

  • If-Modified-Since 包含上次响应的 Last-Modified 时间。
  • If-None-Match 包含上次响应的 ETag 值。

响应(资源未修改)

如果资源未修改,服务器返回 304 状态码,并不包含响应体。

HTTP/1.1 304 Not Modified
Date: Mon, 08 Jun 2024 11:05:00 GMT

客户端收到 304 响应后,会继续使用缓存的数据。

响应(资源已修改)

如果资源已修改,服务器返回新的资源数据和相应的缓存头部信息。

HTTP/1.1 200 OK
Date: Mon, 08 Jun 2024 11:05:00 GMT
Cache-Control: max-age=3600, must-revalidate
Last-Modified: Mon, 08 Jun 2024 11:00:00 GMT
ETag: "9b3a4f5a7d8e2f7c9a"
Content-Type: text/html
Content-Length: 1256

<html>...</html>

在这个响应中,Last-ModifiedETag 值会被更新,客户端会用新的数据替换旧的缓存数据。

总结

1. 初次请求

客户端请求资源,服务器返回资源数据和缓存头部信息。

2. 强缓存

在缓存有效期内,客户端直接从缓存中获取数据,不向服务器发送请求。

3. 协商缓存

缓存过期后,客户端发送验证请求,服务器根据资源是否修改返回相应的状态码:

  • 304(Not Modified):客户端继续使用缓存数据。
  • 200(OK):服务器返回新的资源数据和缓存头部信息,客户端更新缓存。

通过这种机制,HTTP 缓存有效地减少了不必要的网络请求,提高了资源加载速度和用户体验。理解客户端与服务器之间的交互过程,有助于更好地配置和利用缓存机制。

4. 两者对比优先级

在 HTTP 缓存中,优先级决定了缓存机制的适用顺序以及缓存策略的使用顺序。主要的优先级关系是基于 HTTP 头部字段的组合和具体策略。以下是详细的优先级解释:

优先级原则

1. 明确的禁止缓存指令

如果响应中包含明确的禁止缓存指令,如 Cache-Control: no-store,则这些指令具有最高优先级。无论其他缓存头部如何设置,响应都不会被缓存。

Cache-Control: no-store
2. 强缓存指令

在没有禁止缓存指令的情况下,强缓存指令的优先级次之。这些指令包括 Cache-Control: max-ageExpires。其中,Cache-Control 的优先级高于 Expires

Cache-Control
Cache-Control: max-age=3600
Expires
Expires: Wed, 21 Oct 2023 07:28:00 GMT

如果两者同时存在,Cache-Control 会覆盖 Expires

Cache-Control: max-age=3600
Expires: Wed, 21 Oct 2023 07:28:00 GMT
3. 协商缓存

如果没有强缓存指令,或者强缓存已过期,协商缓存指令将生效。常用的协商缓存头部包括 Last-ModifiedETag,客户端会在请求中使用 If-Modified-SinceIf-None-Match 进行验证。

Last-Modified
Last-Modified: Wed, 21 Oct 2020 07:28:00 GMT
ETag
ETag: "686897696a7c876b7e"
客户端请求中的条件头部
If-Modified-Since: Wed, 21 Oct 2020 07:28:00 GMT
If-None-Match: "686897696a7c876b7e"
4. 特殊的 Cache-Control 指令

某些 Cache-Control 指令会影响上述优先级,包括:

  • no-cache:强制客户端在使用缓存数据前验证资源的新鲜度。
  • must-revalidate:缓存过期后,必须向服务器重新验证。
No-cache 示例
Cache-Control: no-cache
Must-revalidate 示例
Cache-Control: must-revalidate

客户端与服务端的交互过程

示例 1:禁止缓存

客户端请求资源,服务器返回响应并明确禁止缓存:

请求
GET /resource HTTP/1.1
Host: www.example.com
响应
HTTP/1.1 200 OK
Cache-Control: no-store
Content-Type: text/html
Content-Length: 1234

<html>...</html>

结果:客户端不会缓存响应数据。

示例 2:强缓存(Cache-Control 优先级高于 Expires)

服务器设置强缓存指令:

请求
GET /resource HTTP/1.1
Host: www.example.com
响应
HTTP/1.1 200 OK
Cache-Control: max-age=3600
Expires: Wed, 21 Oct 2023 07:28:00 GMT
Content-Type: text/html
Content-Length: 1234

<html>...</html>

结果:客户端缓存数据 3600 秒(1 小时),Cache-Control 优先于 Expires

示例 3:协商缓存

强缓存过期后,客户端发起协商缓存请求:

初次请求
GET /resource HTTP/1.1
Host: www.example.com
初次响应
HTTP/1.1 200 OK
Cache-Control: max-age=10
Last-Modified: Wed, 21 Oct 2020 07:28:00 GMT
ETag: "686897696a7c876b7e"
Content-Type: text/html
Content-Length: 1234

<html>...</html>
强缓存过期后客户端请求
GET /resource HTTP/1.1
Host: www.example.com
If-Modified-Since: Wed, 21 Oct 2020 07:28:00 GMT
If-None-Match: "686897696a7c876b7e"
响应(资源未修改)
HTTP/1.1 304 Not Modified
Date: Mon, 08 Jun 2024 10:05:00 GMT

结果:服务器返回 304,客户端继续使用缓存数据。

示例 4:特殊 Cache-Control 指令

服务器响应中包含 no-cachemust-revalidate 指令:

请求
GET /resource HTTP/1.1
Host: www.example.com
响应
HTTP/1.1 200 OK
Cache-Control: no-cache
Last-Modified: Wed, 21 Oct 2020 07:28:00 GMT
ETag: "686897696a7c876b7e"
Content-Type: text/html
Content-Length: 1234

<html>...</html>

结果:客户端每次使用缓存前必须向服务器验证数据的新鲜度。

总结

HTTP 缓存的优先级从高到低依次为:

  1. 明确的禁止缓存指令(如 Cache-Control: no-store
  2. 强缓存指令(如 Cache-Control: max-age,优先于 Expires
  3. 协商缓存(如 Last-ModifiedETag 结合 If-Modified-SinceIf-None-Match
  4. 特殊 Cache-Control 指令(如 no-cachemust-revalidate

了解这些优先级和交互过程,可以帮助开发者更好地控制缓存行为,提高 Web 应用的性能和用户体验。