强缓存与协商缓存的实现机制

文章目录


前言

强缓存与协商缓存的实现机制

1. 强缓存(强制缓存)

特点:浏览器直接从本地缓存读取资源,不发送请求到服务器。

实现方式:通过 Cache-ControlExpires 响应头控制。

(1) Cache-Control(HTTP/1.1 标准,优先级更高)

• 常见指令:

max-age=<seconds>:缓存有效期(如 max-age=3600 表示 1 小时内有效)。

no-cache:不使用强缓存,直接进入协商缓存(向服务器验证)。

no-store:完全禁用缓存,每次请求都重新获取资源。

public:允许代理服务器缓存(默认 private 仅浏览器缓存)。

immutable:资源永不变,浏览器直接使用缓存(适用于版本化文件名如 main.a1b2c3.js)。

• 示例:

http 复制代码
Cache-Control: public, max-age=3600

(2) Expires(HTTP/1.0 遗留,优先级低于 Cache-Control

• 指定一个绝对过期时间(GMT 格式),若本地时间超过该时间则缓存失效。

• 示例:

http 复制代码
Expires: Wed, 21 Oct 2025 07:28:00 GMT

强缓存生效流程

  1. 浏览器请求资源时,检查 Cache-Control/Expires
  2. 若未过期,直接从 内存缓存(Memory Cache) 或 磁盘缓存(Disk Cache) 加载,HTTP 状态码显示 200 (from cache)。
  3. 若已过期,进入协商缓存流程。

2. 协商缓存(对比缓存)

特点:浏览器向服务器验证缓存是否有效,可能返回 304(Not Modified) 继续使用缓存。

实现方式:通过 Last-Modified/If-Modified-SinceETag/If-None-Match 两组头部控制。

(1) Last-Modified + If-Modified-Since

• 服务器返回 Last-Modified:资源的最后修改时间(GMT 格式)。

• 浏览器下次请求:携带 If-Modified-Since(值为上次的 Last-Modified)。

• 服务器检查:

• 若资源未修改(时间未变),返回 304 Not Modified,浏览器使用缓存。

• 若已修改,返回 200 OK 和新资源。

• 示例:

http 复制代码
# 首次请求(服务器响应)
Last-Modified: Wed, 21 Oct 2025 07:28:00 GMT

# 再次请求(浏览器携带)
If-Modified-Since: Wed, 21 Oct 2025 07:28:00 GMT

(2) ETag + If-None-Match(更精准)

• 服务器返回 ETag:资源的唯一标识符(如哈希值)。

• 浏览器下次请求:携带 If-None-Match(值为上次的 ETag)。

• 服务器检查:

• 若 ETag 匹配,返回 304 Not Modified。

• 若不匹配,返回 200 OK 和新资源。

• 示例:

http 复制代码
# 首次请求(服务器响应)
ETag: "33a64df551425fcc55e4d42a148795d9"

# 再次请求(浏览器携带)
If-None-Match: "33a64df551425fcc55e4d42a148795d9"

协商缓存生效流程

  1. 浏览器发现强缓存失效(或 no-cache),携带 If-Modified-SinceIf-None-Match 向服务器发起请求。

  2. 服务器验证资源是否变化:

    • 未变化 → 返回 304,浏览器使用缓存。

    • 已变化 → 返回 200 和新资源。


对比总结

缓存类型 实现方式 优先级 特点
强缓存 Cache-Control/Expires 直接读缓存,不请求服务器。
协商缓存 Last-Modified/ETag 需向服务器验证,可能返回 304。

实际应用建议

  1. 静态资源(如 JS/CSS/图片):

    • 使用强缓存 + 文件名哈希(如 main.a1b2c3.js),设置 Cache-Control: max-age=31536000, immutable

  2. 动态资源(如 API 数据):

    • 使用 Cache-Control: no-cache + ETag,确保实时性。

  3. 避免缓存问题:

    • 修改资源时更新文件名或 URL 参数(如 ?v=2)。

通过合理配置,可显著减少网络请求,提升页面加载速度! 🚀


1. 缓存配置的三种主要实现方式

(1) 后端代码控制(如Node.js/Java/Python)

适用场景:动态API、需要业务逻辑判断是否缓存。

示例(Node.js Express):

javascript 复制代码
app.get('/data', (req, res) => {
  // 强缓存:1小时有效
  res.set('Cache-Control', 'public, max-age=3600');
  
  // 协商缓存:ETag
  const data = { id: 1, name: 'Example' };
  const etag = require('crypto').createHash('md5').update(JSON.stringify(data)).digest('hex');
  res.set('ETag', etag);
  
  // 检查客户端If-None-Match
  if (req.headers['if-none-match'] === etag) {
    return res.status(304).end(); // 返回304,使用缓存
  }
  
  res.json(data);
});

(2) Web服务器配置(如Nginx/Apache)

适用场景:静态资源(HTML/CSS/JS/图片)的缓存。

Nginx示例:

nginx 复制代码
server {
    location /static/ {
        # 强缓存:1年(适用于版本化文件名如main.a1b2c3.js)
        add_header Cache-Control "public, max-age=31536000, immutable";
        
        # 协商缓存:Last-Modified/ETag(默认启用,无需额外配置)
    }

    location /api/ {
        # 动态接口禁用强缓存,只用协商缓存
        add_header Cache-Control "no-cache";
        # Nginx会自动处理ETag/Last-Modified(需确保后端未覆盖)
    }
}

(3) CDN控制(如Cloudflare/AWS CloudFront)

适用场景:全球加速的静态资源缓存。

Cloudflare规则示例:

• 缓存规则:匹配URL路径(如/images/*),设置缓存有效期(如1小时)。

• 边缘缓存TTL:覆盖源站的Cache-Control头。


2. 缓存策略选择与优先级
(1) 缓存配置的优先级

  1. CDN设置 > Nginx配置 > 后端代码

    • 如果CDN设置了缓存规则,它会覆盖Nginx或后端的Cache-Control头。

    • 如果Nginx配置了add_header,它会覆盖后端代码的响应头。

(2) 如何决定使用哪种方式?

场景 推荐方式 理由
静态资源(JS/CSS/图片) Nginx/CDN 高效、无需业务逻辑,直接通过文件名哈希(如main.a1b2c3.js)和强缓存优化。
动态API数据 后端代码 需要根据业务逻辑判断是否缓存(如用户隐私数据不可缓存)。
全局缓存策略 CDN 统一管理所有边缘节点的缓存行为,适合多地域部署。

(3) 强制禁用缓存的场景

• 需要实时数据的API(如股票价格):

http 复制代码
Cache-Control: no-store

• 用户敏感信息(如个人资料):

http 复制代码
Cache-Control: private, no-cache

3. 实战建议
(1) 静态资源优化

nginx 复制代码
location /assets/ {
    # 文件名带哈希(如main.a1b2c3.js),强缓存1年
    add_header Cache-Control "public, max-age=31536000, immutable";
}

• 使用Webpack/Vite等工具生成哈希文件名,确保内容变化后URL改变。

(2) 动态API优化

javascript 复制代码
// 后端代码(Express/Koa)
res.set({
    'Cache-Control': 'no-cache', // 禁用强缓存,但允许协商缓存
    'ETag': generateETag(data)   // 基于内容生成ETag
});

(3) 调试缓存行为

• Chrome DevTools → Network → 查看请求头(Cache-Control/ETag)和响应状态(200/304)。

• cURL命令测试:

bash 复制代码
curl -I http://example.com/resource
# 检查响应头中的Cache-Control/ETag

总结

• 谁控制缓存?

• 静态资源 → Nginx/CDN

• 动态API → 后端代码

• 全局策略 → CDN

• 如何选择?

• 强缓存:Cache-Control: max-age=3600(Nginx/CDN优先)。

• 协商缓存:ETag/Last-Modified(后端或Nginx自动处理)。

• 调试工具:Chrome DevTools、cURL、Web服务器日志。

合理配置缓存可显著提升性能,减少服务器压力! 🚀

相关推荐
流星白龙9 小时前
【Redis】4.基本全局命令
数据库·redis·缓存
流星白龙12 小时前
【Redis】3.Redis安装与命令行客户端
数据库·redis·缓存
我不想名字重复18 小时前
redis缓存和数据库数据保持一致
数据库·redis·缓存
时空无限18 小时前
vllm 大模型启动缓存相关环境变量 export
linux·缓存·vllm
流星白龙20 小时前
【Redis】6.计数其他命令
数据库·redis·缓存
正儿八经的少年21 小时前
redis 的大 key 和热 key 详解
数据库·redis·缓存
X-⃢_⃢-X1 天前
十、Redis之布隆过滤器
数据库·redis·缓存
Database_Cool_1 天前
阿里云 Tair(企业级内存数据库)vs 腾讯云 Redis 云缓存深度对比:性能/数据结构/成本全维度 Benchmark
数据库·阿里云·缓存
流星白龙1 天前
【Redis】1.Redis特性
数据库·redis·缓存
chexus1 天前
21. 深入 Nginx HTTP 缓存源码:CDN功能
nginx·http·缓存