解释在 CDN 缓存下实现平滑版本回滚的方案
解读
面试官想确认两点:
- 你是否理解 CDN 边缘节点缓存带来的“版本滞后”风险;
- 你是否能用 Grunt 这类构建工具把“回滚”做成一条可灰度、可观测、可一键回退的流水线,而不是“删缓存、等 10 分钟、全站 502”的野路子。
国内主流 CDN(阿里云 CDN、腾讯云 ECDN、百度云加速)默认缓存时间 10 min~24 h,且节点分布广,TTL 未到期时用户仍可能拿到旧资源;同时微信、QQ、UC 等超级 App 自带私有缓存,进一步放大回滚难度。 因此方案必须“双轨”:一边让 CDN 快速失效,一边让页面能瞬间指向另一套干净资源。
知识点
- Grunt 指纹化(grunt-rev / grunt-filerev):在文件名中注入 8 位 hash,实现“文件不变则 URL 不变,文件一变则新 URL”,让旧版本天然成为不可变对象。
- Grunt 路径替换(grunt-usemin / grunt-replace):自动把 html/css/js 中的静态引用替换成带 hash 的新 URI,保证上线即命中 200 新资源。
- 非覆盖式发布:每次构建输出到独立目录
/release/v{version}.{timestamp}/,回滚只需把 html 入口的window.resourceBase指向上一个目录即可,无需清理 CDN。 - 国内 CDN 缓存失效手段:
- 目录刷新(阿里云 RefreshDir):支持通配
https://static.example.com/release/v1.2.3/*,平均 5~7 min 全国失效; - 预热(PushCache):回滚后立刻把旧版本重新预热到边缘,降低回源带宽。
- 目录刷新(阿里云 RefreshDir):支持通配
- 灰度回滚:通过 Cookie/Header 把 5% 用户流量打到新版本,出问题瞬间把边缘规则切回旧版目录,实现“秒级”回滚。
- Grunt 自动化钩子:在
grunt.registerTask('rollback')里顺序执行:
① 调用 CDN 开放 API 刷新目录;
② 修改 Nginx 或 OSS 静态托管的index.html指向上一版本;
③ 触发钉钉/飞书 Webhook 通知版本号与回滚时间;
④ 生成回滚报告 JSON,供运维平台归档。
答案
“平滑回滚”核心思路是让版本与 URL 一一对应,再让入口文件(唯一不被 CDN 长缓存的 html)可热切换。具体步骤如下:
- Grunt 构建阶段:
- 使用
grunt-filerev给所有 js/css/img 加 hash,输出到/release/v1.2.4.202507041430/; grunt-usemin把 html 里的引用同步改写;- 生成
manifest.json记录版本号与文件映射,供回滚脚本读取。
- 使用
- 发布阶段:
- 将
/release/v1.2.4.202507041430/整目录上传到 OSS 并设置Cache-Control: max-age=31536000, immutable; - 更新
index.html(存放在根目录,缓存 30 s)中的window.V = 'v1.2.4.202507041430',用户下次刷新即拉新资源。
- 将
- 回滚阶段:
- 执行
grunt rollback --to=v1.2.3.202507031200; - 脚本调用阿里云 CDN RefreshDir 接口,刷新新版本目录,防止仍有用户被边缘节点返回 404;
- 把
index.html中的window.V改回旧版本号,上传 OSS 并设置Cache-Control: no-cache; - 触发预热接口,把旧版本目录重新推送到全国边缘,保证回滚后首屏 200 ms 内加载;
- 灰度验证 1 min 无异常,再全量开放;若仍异常,可继续回滚到更老版本,全程用户无感知。
- 执行
- 兜底策略:
- 在页面注入
__BUILD_TIME__变量,前端监控发现错误率飙升时,可自动调用location.reload(true)强制回源,绕过本地缓存; - 对超级 App 内嵌 WebView,采用“带版本号的离线包”机制,回滚时直接下发旧包,实现端侧零等待。
- 在页面注入
拓展思考
- 双 CDN 热备:主走阿里云,备走腾讯云,Grunt 构建后并行上传两份,回滚时改 DNS 解析即可,5 min 内完成跨云切换。
- 边缘函数回滚:利用阿里云 CDN 的 EdgeRoutine,在回滚阶段把请求 rewrite 到旧目录,无需改源站,实现 1 min 内全球生效。
- 自动化决策:在 Grunt 流水线里集成 Sentry 错误率 API,当 5 min 错误率 > 1% 时自动触发
grunt rollback,把“人工回滚”升级为“无人值守回滚”。