0%

HTTP缓存

HTTP 缓存:提升 Web 性能的核心机制

HTTP 缓存是优化 Web 性能的关键技术,通过在客户端(如浏览器)存储已请求的资源副本,减少重复向服务器请求的次数,从而降低网络延迟、节省带宽并提升用户体验。其核心逻辑是:客户端首次请求资源时缓存数据,后续请求优先使用缓存(若有效),否则向服务器重新获取

HTTP 缓存的基本原理

HTTP 缓存的工作流程可概括为:

  1. 首次请求:客户端向服务器请求资源,服务器返回资源并在响应头中附加缓存规则(如过期时间、修改标识)。
  2. 缓存存储:客户端将资源和缓存规则一起保存到本地缓存(如浏览器的内存、磁盘)。
  3. 后续请求:客户端先检查本地缓存是否有效:
    • 若缓存有效,直接使用缓存数据(缓存命中);
    • 若缓存无效,向服务器重新请求资源,并更新缓存(缓存失效)。

HTTP 缓存的两类核心规则

HTTP 缓存通过响应头中的字段定义缓存策略,主要分为基于过期时间的缓存基于资源修改的缓存两大类,两者可协同工作。

基于过期时间的缓存:Expires 与 Cache-Control

这类规则通过指定资源的 “有效期”,让客户端直接判断缓存是否可用,无需向服务器确认,属于强缓存(不发起网络请求,直接使用缓存)。

(1)Expires(HTTP/1.0)
  • 作用:响应头字段,值为一个具体的 GMT 时间(如Expires: Wed, 23 Aug 2025 12:00:00 GMT),表示资源的过期时间。
  • 判断逻辑:客户端下次请求时,若当前时间早于Expires 值,则直接使用缓存;否则认为缓存失效,需重新请求服务器。
  • 局限性:
    • 依赖客户端本地时间,若客户端时间与服务器时间不一致(如时区偏差、时钟错误),会导致缓存判断失效。
    • 仅在 HTTP/1.0 中使用,HTTP/1.1 中被Cache-Control替代。
(2)Cache-Control(HTTP/1.1)

Cache-Control是 HTTP/1.1 中定义的核心缓存控制字段,优先级高于Expires,支持更灵活的缓存策略,其取值可组合使用。

常见取值及含义

  • public:客户端和代理服务器(如 CDN)都可缓存该资源(适合公开资源)。
  • private:仅客户端可缓存,代理服务器不可缓存(适合用户私有数据,如个人主页)。
  • max-age=xx:资源的有效期为xx秒(从请求成功时开始计时),优先级高于Expires。例如max-age=3600表示缓存 1 小时内有效。
  • s-maxage=xx:仅对代理服务器生效,覆盖max-age(如 CDN 缓存时间)。
  • no-cache:缓存有效,但使用前必须向服务器确认资源是否更新(不直接使用缓存,需配合后续验证机制)。
  • no-store:完全禁止缓存,客户端和服务器都不存储任何资源副本(适合敏感数据,如支付信息)。
  • must-revalidate:缓存过期后,必须向服务器验证资源有效性,不可使用过期缓存。

示例

1
Cache-Control: public, max-age=3600, must-revalidate

表示资源可被客户端和代理缓存,有效期 1 小时,过期后必须验证是否更新。

基于资源修改的缓存:Last-Modified 与 ETag

当强缓存(Expires/Cache-Control)失效时,客户端需向服务器确认资源是否已更新,属于协商缓存(需发起网络请求,但可能不返回完整资源)。

(1)Last-Modified 与 If-Modified-Since
  • Last-Modified:服务器在响应头中返回的资源最后修改时间(如Last-Modified: Tue, 20 Aug 2025 08:00:00 GMT)。
  • If-Modified-Since:客户端后续请求时,在请求头中携带该字段,值为上次获取的Last-Modified时间,用于询问服务器 “资源在该时间后是否被修改”。

验证逻辑

  • 若服务器判断资源未被修改(最后修改时间 ≤ If-Modified-Since),返回状态码304 Not Modified,不返回资源体,客户端使用缓存。
  • 若资源已被修改(最后修改时间 > If-Modified-Since),返回状态码200 OK和新资源,客户端更新缓存。

局限性

  • 只能精确到秒级,若资源在 1 秒内多次修改,无法识别。
  • 某些操作(如文件重命名但内容不变)会改变修改时间,但资源实际未更新,导致不必要的重新请求。
(2)ETag 与 If-None-Match

为解决Last-Modified的局限性,HTTP 引入了基于资源内容的唯一标识机制。

  • ETag:服务器为资源生成的唯一标识(如ETag: "abc123"),资源内容变化时ETag会更新(无论修改时间是否变化)。
  • If-None-Match:客户端后续请求时,在请求头中携带该字段,值为上次获取的ETag,用于询问服务器 “资源的ETag是否与该值匹配”。

验证逻辑

  • ETag匹配(资源未修改),服务器返回304 Not Modified,客户端使用缓存。
  • ETag不匹配(资源已修改),服务器返回200 OK和新资源,客户端更新缓存。

优势

  • 基于内容而非时间判断,更精准(如识别 1 秒内的修改、内容不变的重命名)。
  • 支持强验证(精确匹配)和弱验证(ETag: W/"abc123",允许内容轻微修改)。

缓存规则的优先级与协同工作

HTTP 缓存规则的生效顺序如下:

  1. Cache-Control(HTTP/1.1)优先级最高,若存在则忽略Expires
  2. Cache-Controlmax-age未过期,直接使用强缓存。
  3. 若强缓存失效,客户端发起请求,携带If-Modified-Since(对应Last-Modified)和If-None-Match(对应ETag)。
  4. 服务器优先验证ETag(精度更高),再验证Last-Modified,返回304200

示例流程

  1. 客户端首次请求style.css,服务器返回:

    1
    2
    3
    4
    5
    HTTP/1.1 200 OK
    Cache-Control: max-age=3600
    Last-Modified: Tue, 20 Aug 2025 08:00:00 GMT
    ETag: "v1.0"
    Content-Length: 1024

    客户端缓存style.css,有效期 1 小时。

  2. 30 分钟后请求:max-age未过期,直接使用缓存(不发请求)。

  3. 2 小时后请求:max-age过期,客户端发送请求:

    1
    2
    3
    GET /style.css HTTP/1.1
    If-Modified-Since: Tue, 20 Aug 2025 08:00:00 GMT
    If-None-Match: "v1.0"
  4. 服务器判断资源未修改,返回:

    1
    2
    HTTP/1.1 304 Not Modified
    Cache-Control: max-age=3600

    客户端继续使用缓存,并更新缓存有效期。

缓存的应用场景与最佳实践

  1. 静态资源(如 CSS、JS、图片)
    • 适用强缓存:设置较长的max-age(如max-age=31536000,1 年)。
    • 配合版本控制:资源更新时修改文件名(如style.v2.css),避免缓存干扰。
  2. 动态资源(如 API 接口)
    • 禁用强缓存:使用Cache-Control: no-cache强制每次验证。
    • 启用协商缓存:通过ETagLast-Modified减少重复传输。
  3. 敏感资源(如用户信息、支付页面)
    • 禁用缓存:Cache-Control: no-store,确保每次从服务器获取最新数据。
  4. CDN 缓存
    • 使用publics-maxage控制 CDN 缓存时间,减轻源服务器压力。

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10