一、缓存策略与生命周期
1. CDN缓存机制
- 强缓存:通过
Cache-Control: max-age=3600
或Expires
控制,CDN直接返回本地副本(无需请求服务器); - 协商缓存:通过
ETag
和Last-Modified
验证资源是否更新,若未更新则返回304状态码; - CDN节点层级:边缘节点(离用户近)→ 区域节点→ 源站,逐层回源验证。
2. 用户本地缓存
- 浏览器缓存:HTML、CSS、JS、图片等静态资源按HTTP头规则缓存;
- Service Worker:可拦截网络请求,实现离线缓存(需手动控制更新)。
二、缓存更新触发机制
1. CDN侧更新
- 主动刷新(Purge):
- 通过CDN服务商API手动刷新指定资源(如
curl -X PURGE https://cdn.example.com/app.js
); - 适用于紧急更新(如修复JS漏洞),刷新后CDN节点会重新从源站拉取资源。
- 通过CDN服务商API手动刷新指定资源(如
- 缓存时间到期:
- 资源超过
max-age
设置的时间后,CDN自动回源验证。
- 资源超过
2. 用户本地缓存更新
- 资源URL变更:
- 通过文件名哈希(如
app.1234abcd.js
)强制用户下载新资源; - 适用于HTML中引用的静态资源(如CSS、JS)。
- 通过文件名哈希(如
- Service Worker更新:
- 注册新的Service Worker脚本,通过
self.skipWaiting()
强制激活; - 使用
Cache Storage API
删除旧缓存(如caches.delete('old-cache')
)。
- 注册新的Service Worker脚本,通过
三、版本控制最佳实践
1. 文件名哈希(推荐方案)
- 实现方式:
- 构建工具(如Webpack、Vite)自动生成带哈希的文件名(如
app.[contenthash].js
); - HTML中动态引用新文件名(如通过模板替换)。
- 构建工具(如Webpack、Vite)自动生成带哈希的文件名(如
- 优势:
- 强缓存命中率高(不同版本URL不同);
- 无需手动刷新CDN(新资源自动推送到CDN节点)。
2. 查询参数版本号
- 实现方式:
- 在URL后添加版本号(如
app.js?v=20230704
); - 版本号可通过构建工具自动替换(如package.json中的version字段)。
- 在URL后添加版本号(如
- 注意事项:
- CDN需配置忽略查询参数(部分CDN默认不缓存带查询参数的资源);
- 可能导致旧资源长期留在CDN节点(需手动刷新)。
3. HTML动态加载
- 实现方式:
// 通过JS动态加载资源,版本号存储在配置文件中 const version = '20230704'; document.write(`<script src="app.js?v=${version}"></script>`);
- 适用场景:需要实时控制资源版本的场景(如A/B测试)。
四、风险应对与监控
1. 缓存更新失败的处理
- 双缓存策略:
- Service Worker同时缓存当前版本和上一版本资源,确保更新失败时回退;
- 示例:
self.addEventListener('install', event => { event.waitUntil( caches.open('v2').then(cache => cache.addAll(['/app.js'])) ); });
- CDN预热:
- 更新后主动向CDN节点推送新资源(如使用阿里云CDN的“预热”功能)。
2. 监控与告警
- CDN状态监控:
- 通过服务商API获取缓存命中率、回源率等指标;
- 设置异常告警(如回源率突然升高)。
- 用户端监控:
- 通过JS埋点统计用户加载失败率;
- 使用Performance API监测资源加载时间。
五、问题
1. 如何确保HTML文件本身被更新?
- 答:
HTML通常设置较短的缓存时间(如Cache-Control: max-age=60
)或禁用强缓存(Cache-Control: no-cache
),确保每次请求都验证最新版本。
同时,HTML中引用的静态资源(如CSS、JS)使用哈希文件名,保证内容变更时强制更新。
2. CDN缓存刷新后,用户仍看到旧资源怎么办?
- 答:
- 检查源站:确认源站文件是否已更新;
- CDN节点预热:主动向边缘节点推送新资源;
- 用户端强制刷新:引导用户使用
Ctrl+F5
(Chrome)或清除浏览器缓存; - 紧急降级:通过Service Worker回退到上一版本资源。
3. 如何平衡缓存命中率与更新及时性?
- 答:
- 静态资源(如JS、CSS、图片):使用长缓存(如
max-age=31536000
)+ 哈希文件名,确保内容不变时充分利用缓存; - 动态资源(如API响应):使用短缓存或协商缓存(如
ETag
),保证数据实时性; - HTML文件:设置中等缓存时间(如5分钟),平衡加载速度与更新频率。
- 静态资源(如JS、CSS、图片):使用长缓存(如
六、总结
- 静态资源:哈希文件名 + 超长缓存(1年),无需手动刷新CDN;
- HTML/动态内容:短缓存 + 协商验证,确保及时更新;
- 紧急情况:CDN手动刷新 + Service Worker双缓存回退;
- 监控保障:CDN指标监控 + 用户端异常告警。