ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Agones 云构建缓存:基于 Cloud Build 的 save_cache / restore_cache 构建缓存实践指南

Agones 云构建缓存:基于 Cloud Build 的 save_cache / restore_cache 构建缓存实践指南 游戏开发云原生【免费下载链接】agonesDedicated Game Server Hosting and Scaling for Multiplayer Games on Kubernetes项目地址https://gitcode.com/gh_mirrors/ag/agones点击查看免费下载本文介绍 Agones 仓库中随附的 Cloud Build 缓存构建器cache builders——save_cache与restore_cache。这对工具用于在两次 Google Cloud Build 构建之间把文件如依赖目录、编译产物打包缓存到 GCS 存储桶或本地目录从而显著缩短 CI 构建时长。读完本文你将掌握这两个构建器的全部参数语义、checksum辅助脚本的用法、--key_fallback回退机制以及可直接复用到自有cloudbuild.yaml中的完整示例。一、背景这套缓存工具的来源与定制Agones 仓库中的build/build-image/cache/README.md明确指出这份文档与实现最初源自 Google Cloud Platform 社区贡献镜像合集 [cloud-builders-community] 中的cache构建器该合集中的镜像可作为 Google Cloud Build 的构建步骤直接使用。Agones 在将其引入仓库时做了唯一的关键改动把所有镜像标签从 Google Container RegistryGCR迁移到了Google Artifact RegistryGAR即镜像地址统一使用us-docker.pkg.dev/$PROJECT_ID/ci/...的形式。这一点在本文的所有示例中都能看到——凡是构建步骤的name字段都指向us-docker.pkg.dev域下的 Artifact Registry 镜像。这一对构建器一存一取、相互配合负责在构建与构建之间缓存文件既可以把缓存打包上传到 GCS 存储桶也可以仅落到本地磁盘目录例如配合 Cloud Build 的卷volumes跨步骤共享。二、save_cache把目录打包并写入缓存2.1 参数一览所有需要值的选项均采用--optionvalue或-ovalue的形式这样在 YAML 文件中看起来整齐且不易出错选项说明-b, --bucket缓存上传到的云存储桶路径。[可选]-o, --out缓存写入的本地输出目录。[可选]-k, --key本次缓存文件的缓存键cache key。[可选]-p, --path要存入缓存的文件/目录可重复指定。-t, --threshold并行复合上传阈值parallel composite upload threshold。[默认50M]-n, --no-clobber若缓存文件已存在于 GCS 中则跳过本次保存。必选约束--bucket与--out二者必须提供其一。若指定--bucket缓存文件会上传到给定的 GCS 桶路径若指定--out缓存文件会写入磁盘上指定的目录。关键语义对应 save_cache 脚本 的实现--key用于标识缓存文件。同一 key 下已存在的缓存文件会被本次内容覆盖。--path可以重复多次有多少目录就传多少次。恢复时restore 阶段这些目录会保持原有的目录结构被还原到磁盘上因此非常适合缓存vendor/、node_modules/、~/.gradle之类的依赖目录或编译中间产物。--no-clobber只在与--bucket搭配时有效若 GCS 中已有同 key 的缓存文件则跳过创建与上传。这适用于依赖全部锁死版本、构建过程不会改动缓存内容的场景——例如 Go 模块全部由go.sum锁定、前端依赖由package-lock.json锁定的项目。此时每次构建都免去重新打包上传进一步缩短构建时长。如果--no-clobber被使用而--bucket为空脚本会直接报错退出。2.2 底层实现原理从源码 save_cache 可以看出实际执行链路脚本用for i in $; do case $i in ...)解析全部参数遇到未知参数或缺少--key/--path时打印用法并退出exit 1。通过eval KEY$KEY对 key 字符串求值使$(...)形式的命令替换如$( checksum ... )能展开为真实值。组成缓存文件路径CACHE_FILE${OUT_DIR}/${KEY}.tgz——可见缓存文件是.tgz压缩包。若启用--no-clobber先用gsutil ls $BUCKET_FILE探测$BUCKET/$KEY.tgz是否已存在存在则直接 exit 0。用tar cpzf $CACHE_FILE ${PATHS[]} -P把多个 path 打进同一个 tgz-P保留绝对路径语义。若指定了--bucket用gsutil -o GSUtil:parallel_composite_upload_threshold${THRESHOLD} cp -R上传其中阈值正是--threshold参数默认50M用于控制多大文件启用并行复合上传。三、restore_cache按 key 取回缓存并还原目录3.1 参数一览选项说明-b, --bucket下载缓存文件的云存储桶路径。[可选]-s, --src缓存所在本地目录。[可选]-k, --key缓存文件的缓存键。[可选]-kf, --key_fallback精确 key 未命中时使用的缓存键回退模式。[可选]必选约束--bucket与--src二者必须提供其一。指定--bucket时从给定 GCS 桶路径下载缓存指定--src时从磁盘上的目录读取缓存。--key用于精确匹配缓存文件。而--key_fallback的价值在于当指定--key发生缓存未命中cache miss时用它提供的模式去桶中捞取最近一次与该模式匹配的缓存文件——这正是 CI 中最常见的场景依赖清单没变但 key 里的时间戳/构建号变了此时回退到最近一次可用缓存依然能命中避免全量重装依赖。3.2 底层实现原理从源码 restore_cache 可以看到完整的恢复逻辑GCS 精确命中REMOTE_CACHE_FILE${BUCKET}/${KEY}.tgz用gsutil -q stat探测存在性命中则gsutil -q cp下载到SRC_DIRtar xpzf解压还原随后删除本地的 tgz 临时文件。GCS 未命中 无回退直接输出 Can not restore cache! 并以 exit 0 正常结束——注意恢复失败并不使构建失败这是刻意设计让没有缓存时构建照常执行代价是多花时间重装依赖。GCS 未命中 有回退执行gsutil ls -l $BUCKET/$KEY_FALLBACK_PATTERN** | sort -k 2,2r | grep -m 1 -i $KEY_FALLBACK_PATTERN | awk {print $3}即按最后修改时间倒序取最近一个匹配文件下载并解压。本地--src模式直接从${SRC_DIR}/${KEY}.tgz解压还原。与save_cache一致key 字符串同样先经过eval求值因此$( checksum ... )在 restore 侧同样可用。四、checksum辅助脚本让缓存键随内容变化随着项目演进缓存需求会变依赖被移除、版本被升级时旧版本的依赖缓存不再有价值。因此文档强烈建议在这些变化发生时更新缓存键而不是一直复用同一个 key 造成缓存陈旧或白白存储。为此构建器自带一个checksum辅助脚本位于 checksum实现只有一行核心逻辑echo $(cksum $ | cut -d -f1) | tr -它基于 POSIXcksum对传入的文件列表计算 CRC 校验值并用-连接多个文件的校验和从而得到一个由关键文件内容派生出的稳定键。用法是在--key参数中用$()包裹命令替换--keybuild-cache-$(checksum build.gradle)-$(checksum dependencies.gradle)这样只要build.gradle或dependencies.gradle的内容发生变化key 就会改变进而产生一个新缓存内容不变则 key 不变旧缓存可直接复用。类似的思路完全可以迁移到 Agones 自己的构建流程例如对go.mod/go.sum、package.json/package-lock.json做 checksum让缓存键精确反映依赖清单的变化。五、缓存存储成本治理对象生命周期规则为了防止为过期的缓存文件持续付费文档建议在缓存桶上配置Object Lifecycle Rule对象生命周期规则删除超过 30 天的对象。例如在 GCS 控制台为桶添加一条规则删除早于 30 天的对象即可让不再被任何构建引用的旧 key 缓存自动清理。这一治理手段与checksum动态键配合能长期保持缓存桶常用即存在、过期即回收。六、完整示例五种典型组合以下示例均来自 cache 构建器 README可在你自己的 Cloud Build 构建中直接套用。6.1 保存缓存到 GCS 桶带 checksum下面的cloudbuild.yaml片段把path参数中的文件与目录保存为 GCS 桶gs://$CACHE_BUCKET/下的缓存文件。每当cloudbuild.yaml本身被修改时key 更新从而产生一个新缓存- name: us-docker.pkg.dev/$PROJECT_ID/ci/save_cache args: - --bucketgs://$CACHE_BUCKET/ - --keyresources-$( checksum cloudbuild.yaml ) - --path.cache/folder1 - --path.cache/folder2/subfolder36.2 保存缓存到 GCS 桶no-clobber 跳过已存在缓存如果构建过程只在cloudbuild.yaml变化时才改动缓存内容那么当缓存已存在于 GCS 时可以直接跳过再次保存缩短构建- name: us-docker.pkg.dev/$PROJECT_ID/ci/save_cache args: - --bucketgs://$CACHE_BUCKET/ - --keyresources-$( checksum cloudbuild.yaml ) - --path.cache/folder1 - --path.cache/folder2/subfolder3 - --no-clobber6.3 保存缓存到本地文件把path参数中的文件保存为out参数指定目录下的缓存文件。注意这里通过volumes声明了一个名为cache的卷挂载到/cache以便同一构建中的其他步骤或后续 restore 步骤共享该目录- name: us-docker.pkg.dev/$PROJECT_ID/ci/save_cache args: - --out/cache/ - --keyresources-$( checksum cloudbuild.yaml ) - --path.cache/folder1 - --path.cache/folder2/subfolder3 volumes: - name: cache path: /cache6.4 从 GCS 桶恢复缓存按key从缓存桶中取回对应的压缩缓存文件若存在并还原目录- name: us-docker.pkg.dev/$PROJECT_ID/ci/restore_cache args: - --bucketgs://$CACHE_BUCKET/ - --keyresources-$( checksum cloudbuild.yaml )6.5 从本地文件恢复缓存从本地文件系统按 key 恢复缓存同样依赖共享卷/cache- name: us-docker.pkg.dev/$PROJECT_ID/ci/restore_cache args: - --src/cache/ - --keyresources-$( checksum cloudbuild.yaml ) volumes: - name: cache path: /cache6.6 带回退键fallback key的恢复当精确 key 未命中时按--key_fallback模式抓取最近一次的匹配缓存。适用于依赖版本偶有更新但绝大多数构建希望沿用最近一次缓存的构建流水线- name: us-docker.pkg.dev/$PROJECT_ID/ci/restore_cache id: restore_cache args: [ --bucketgs://${_CACHE_BUCKET}, --keygradle-$( checksum checksum.txt ), --key_fallbackgradle-, ]注意此处 key 由checksum.txt派生如 gradle 依赖清单而回退模式是gradle-前缀——一旦精确键失配restore 会列出桶内所有gradle-开头的缓存并按时间取最新一份。七、镜像构建与自测仓库内的完整验证流水线这套构建器在 Agones 仓库里并非仅有文档还包含完整的镜像定义与一套自我验证的 Cloud Build 流水线基础镜像 Dockerfile-base基于gcr.io/cloud-builders/gcloud-slim安装gcc / python3-dev / python3-pip / crcmodcrcmod用于 gsutil 的高性能 CRC 校验上传并把checksum、save_cache、restore_cache三个脚本拷入/bin。分发镜像 Dockerfile-save 与 Dockerfile-restore都以us-docker.pkg.dev/${project_id}/ci/cache为基础分别把save_cache、restore_cache设为各自镜像的ENTRYPOINT构建参数project_id由 Cloud Build 的--build-arg注入。构建与测试流水线 cloudbuild.yaml 给出了权威的正确用法参考依次构建cache、save_cache、restore_cache三个镜像_VERSION当前为1.2同时打latest标签然后执行一轮端到端自测——用save_cache --out/cached --keysimple-key-$( checksum cloudbuild.yaml ) --path...保存多级目录结构、校验/cached/simple-key-....tgz存在、清理原文件后调用restore_cache --src/cached恢复最后逐一验证folder1/file1.txt、folder2/subfolder3/file1.txt、rel_folder/file3.txt等文件是否被正确还原。这份自测流水线本身就是绝佳的模板save → verify → clean → restore → verify五步结构完整演示了 key 的 checksum 派生、--path多目录打包、volumes共享、以及恢复后目录结构保持的最终效果。八、在 Agones 构建体系中的实际位置Agones 的持续集成如 cloudbuild.yaml、ci/e2e-test-cloudbuild.yaml、ci/perf-test-cloudbuild.yaml依赖多步骤构建构建产物与测试镜像需要在各阶段之间传递将编译缓存与依赖缓存落地到 GCS 或共享卷是这类长流水线提速的通用手段。build/build-image/cache/目录即是为这套流程提供的开箱即用工具镜像统一构建到us-docker.pkg.dev/$PROJECT_ID/ci/下与仓库 CI 的镜像命名空间保持一致。你可以在此基础上按需扩展如调整_VERSION进行镜像版本管理、用--threshold调优大文件上传并发度而无需从零实现打包上传逻辑。要点回顾save_cache负责打包 上传restore_cache负责下载 还原--bucketGCS 持久缓存与--out/--src卷内临时缓存二选一即可checksum让缓存键跟随依赖内容变化--no-clobber在内容不变时跳过上传--key_fallback保证 key 失配时仍能取到最近可用缓存桶生命周期规则用于回收 30 天以上的陈旧缓存。将这一对构建器接入你的cloudbuild.yaml即可获得一套成熟、可验证的跨构建缓存方案。赞分享游戏开发云原生【免费下载链接】agonesDedicated Game Server Hosting and Scaling for Multiplayer Games on Kubernetes项目地址https://gitcode.com/gh_mirrors/ag/agones点击查看免费下载相关推荐Dalamud构建缓存增量构建与缓存复用Dalamud构建缓存增量构建与缓存复用 概述 Dalamud作为FFXIV最终幻想14的插件框架其构建系统采用现代化的.NET构建工具链。本文将深入探深入解读 buf 的 Imports 缓存基于 bufmodulecache 的模块缓存结构与重建指南深入解读 buf 的 Imports 缓存基于 bufmodulecache 的模块缓存结构与重建指南 导读 本指南以 cmd/buf/testdata/im开发工具代码生成API设计如何永久保存微信聊天记录WeChatMsg完整数据备份与导出指南如何永久保存微信聊天记录WeChatMsg完整数据备份与导出指南 你是否担心珍贵的微信对话会随着时间流逝而消失那些与亲友的重要对话、工作群里的关键信息、学习创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进