1.CDN缓存 2.解决方案 1.CDN缓存 CDN并不会主动把旧包和新包放在一起, 所谓的"新旧包混杂" , 本质是相同文件名的前提下, CDN不同边缘节点的缓存状态不 一致 —— 有的节点存着旧包, 有的节点拉取了新包, 用户访问不同节点就拿到不同版本, 从用户视角看就像是"混在一起了" 1 ) . 前提: 只针对"同名文件" , 比如都是hotupdate. zip 如果热更包文件名不同( v1. 0.0 和v1. 0.1 ) , CDN会把它们当成完全不同的两个文件, 各节点会独立缓存, 根本不存在混杂, 这 也是为什么改文件名能从根源解决问题 混包只发生在"文件名不变, 只替换源站文件" 的场景下, 核心原因: 3 个CDN特性导致节点缓存状态不一致a. 每个CDN节点是"独立的小仓库" , 互相不通气 全国的CDN边缘节点彼此之间没有数据同步, 北京节点存了什么版本、缓存有没有过期, 上海节点完全不知道, 每个节点只管 自己的库存和计时 源站把hotupdate. zip从v1换成v2后, 不会主动通知所有节点"赶紧换包" , 节点们只能靠自己的缓存过期规则判断是否需要 更新b. 缓存过期时间"节点各自计时" , 起点完全不同 节点的缓存有效期, 比如7 天, 是从"这个节点第一次拉取文件的时刻开始算的, 不是源站发布文件的时刻" 比如: - 北京节点1 月1 日9 点被用户触发, 拉取了v1包, 有效期到1 月8 日9 点- 上海节点1 月2 日14 点被触发, 拉取v1包, 有效期到1 月9 日14 点- 源站1 月7 日把文件换成v2后, 北京、上海节点的缓存都没到期, 会继续存着v1包c. 节点只会"被动更新" , 不会主动检查源站 缓存没过期的节点, 会默认自己的库存是"最新的" , 用户请求时直接返回本地旧包, 不会去源站确认"文件是不是换了" 只有两种情况节点会去源站拉取新文件- 节点的缓存过期了, 用户请求时会先去源站校验, 发现文件更新就拉取v2- 节点从来没缓存过这个文件( 新节点/ 无用户访问过) , 用户请求时直接去源站拉取最新的v2最终混杂的结果: "不同节点返回不同版本" , 源站替换同名文件后, CDN的节点会分成三类- ✅ 缓存未过期的节点: 继续返回旧包v1, 比如北京- ❌ 缓存已过期的节点: 去源站拉取新包v2, 返回v2- ❌ 无缓存的节点: 直接去源站拉取新包v2, 返回v2 用户访问CDN时, 会被自动分配到就近的节点: - 被分配到北京节点的用户-> 拿v1旧包- 被分配到上海新节点的用户-> 拿v2新包 从用户视角看, 就是"同一个下载地址, 有的人拿到旧包, 有的人拿到新包" , 也就是"新旧包混在一起了" CDN的"混包" 不是CDN主动将新旧包共存, 而是同名文件下, 各边缘节点的缓存过期时间不同、缓存状态不一致, 导致不同节 点返回不同版本的文件, 最终体现在用户侧的版本混乱; 只要给热更包加唯一标识( 版本号/ 哈希) , 让新旧包文件名不同, CDN 会将它们视为独立资源, 各节点的缓存互不影响, 就彻底不会有混杂问题了2.解决方案 解决"用户识别最新包" 的关键是: 在CDN上放一个固定文件名的版本清单文件( 比如version. json) , 这个文件是"导航页" , 它 本身文件名不变( 但设置短缓存) , 里面记录着最新热更包的"唯一标识文件名" , "版本号" , "CDN地址" 等信息; Unity客户端 启动时, 先下载这个清单文件, 对比本地版本, 就能知道有没有新包、新包的CDN地址是什么, 然后下载对应的包a. 先确定CDN上的文件结构, 这是避免缓存问题的基础
b. 版本清单文件( version. json) 内容示例 这个文件是核心, 内容要包含足够的信息让客户端判断是否更新, 示例如下
- 发布新包时, 只需要修改这个version. json里的内容, 比如把latestVersion改成1.0 .1 , packageName改成新包名, 然后 重新上传到CDN即可- 给这个文件设置CDN缓存策略: Cache- Control: max- age= 60 ( 缓存60 秒) , 确保客户端每次都能拿到最新的清单c. 热更包的命名与缓存- 热更包( Unity的AssetBundle包) 命名必须带唯一标识( 版本号/ 哈希值) 比如: hotupdate_v1. 0.0 . unity3d、hotupdate_v1. 0.1 . unity3d- 给热更包设置CDN长缓存: Cache- Control: max- age= 31536000 ( 缓存1 年) , 因为文件名唯一, 不会和旧包混杂, 缓存越久 越省CDN资源