4. Gradle 缓存同步配置:settings.gradle 中的 buildCache

多模块、多分支、多人协作的大型项目,构建产生的大量中间产物(class 文件、jar、native 库)重复编译会导致构建时间指数级增长。Gradle buildCache 允许将任务输出物持久化到本地或远程存储,后续构建只需从缓存拉取,无需重新执行任务。本章深入 settings.gradle 中的 buildCache 配置块,覆盖远程缓存 URL 与凭据管理、启用/禁用策略,以及生产环境下的调试与优化。

4.1 buildCache 配置模型

buildCache 配置以 DSL 块形式出现在 settings.gradle(或 settings.gradle.kts)中。核心构件包括:

  • local —— 默认启用,基于 ~/.gradle/caches/build-cache-1 目录。
  • remote —— 可选,通过 URL 指向远程缓存服务(HTTP 或 Gradle Enterprise 兼容端点)。
  • enabled / disabled —— 策略级开关,可对 local 和 remote 分别控制。
  • push —— 远程缓存是否允许上传新缓存项。默认仅本地和远程都允许 push。

原理:每个 Task 的 输入哈希(input hash) 决定缓存键。缓存命中时直接反序列化输出物到 build/ 目录;未命中则执行任务并将结果 push 到所有启用了 push 的缓存后端。

4.2 settings.gradle 配置示例

以下为完整的 settings.gradle.kts 配置(Kotlin DSL 版本,Groovy DSL 语法类似):

buildCache {
    // 本地缓存默认启用,但可调整目录大小
    local {
        enabled = true
        // 最大缓存容量,单位字节(默认 10GB)
        maxCacheSize = "20 GB"
        // 缓存项保留时间(默认 7 天)
        removeUnusedEntriesAfterDays = 14
    }

    // 配置远程缓存
    remote(HttpBuildCache::class.java) {
        url = uri("https://gradle-cache.team.example.com/cache")
        // 基本认证凭据
        credentials {
            username = "cache-reader"
            password = project.findProperty("cachePassword") as String?
        }
        // 启用/禁用策略
        isEnabled = true
        // 是否允许上传新缓存项
        isPush = false     // 多数场景下只从远程读取
    }
}

若使用 Groovy DSL,等价写法为:

buildCache {
    local {
        enabled true
        maxCacheSize = '20 GB'
        removeUnusedEntriesAfterDays = 14
    }
    remote(HttpBuildCache) {
        url = 'https://gradle-cache.team.example.com/cache'
        credentials {
            username = 'cache-reader'
            password = project.findProperty('cachePassword')
        }
        enabled = true
        push = false
    }
}

4.3 启用/禁用策略详解

策略DSL 属性作用域说明
全面禁用buildCache { isEnabled = false }全局所有缓存(local + remote)停用,构建完全不使用缓存。
仅本地remote { isEnabled = false } 或移除 remote 块远程仅在本地缓存中读写,常用于离线环境。
只读远程remote { isPush = false }远程拉取远程缓存,但不上传新项,避免污染公共缓存。
CI 只写remote { isEnabled = true; isPush = true },本地禁用远程CI 任务编译后将结果上传到远程,开发者仅从远程拉取。
按项目条件利用 gradle.startParameter.isBuildCacheEnabled运行时在 buildCache 块内判断是否启用,例如 if (!gradle.startParameter.isBuildCacheEnabled) return。

推荐 CI 策略:CI 节点启用远程缓存 push,开发机只读远程 pull。通过 isPush = false 避免本地开发机意外上传重复或不完整的缓存项。

4.4 远程缓存 URL 与凭据管理

4.4.1 URL 格式

buildCache 的 url 指向一个 HTTP/HTTPS 端点,该端点必须实现 Gradle 缓存协议。常见后端:

  • Gradle Enterprise / Develocity 内置缓存
  • Nginx + 自定义缓存存储(基于 S3/MinIO)
  • 专用缓存服务器(如 gradle-cache-backend 开源方案)

4.4.2 凭据注入方式

避免在版本库中硬编码密码,推荐以下方式:

  1. Gradle 属性文件:在 ~/.gradle/gradle.properties 或 CI 环境变量中设置 cachePassword=xxx。
  2. 命令行参数:-PcachePassword=xxx 传递。
  3. 文件系统凭据:Gradle 7.6+ 支持 HttpBuildCache.credentials { file = uri("file:///etc/gradle-cache-credentials") } 读取文件内容。

安全提示:不要在 settings.gradle 中直接硬编码密码!若使用文件凭据,确保文件权限为 600,仅 Gradle 进程可读。

4.5 调试缓存行为

4.5.1 启动日志

在 gradle.properties 或命令行添加:

org.gradle.caching.debug=true

构建日志会输出每条任务的缓存查找、命中、存储信息:

CompileJava: cache hit, entry key=abc123
ProcessResources: cache miss, storing to remote cache...

4.5.2 强制禁用缓存测试

临时验证构建是否依赖缓存产物:

gradle clean build --no-build-cache

若开启 --build-cache 与禁用的任务输出一致,说明缓存逻辑正确。

4.6 性能与稳定性优化

  • 合理设置本地缓存大小:maxCacheSize = "50 GB"(根据项目产物体积调整),避免频繁清理或磁盘占满。
  • 远程缓存超时与重试:Gradle HTTP 缓存客户端默认 30s 超时,可通过系统属性调整:-Dorg.gradle.cache.http.connectTimeout=10000。
  • 缓存键冲突预防:将项目版本、JDK 版本纳入输入参数,避免不同环境使用相同缓存导致异常。可通过 taskOutputs.cacheIf { true } 配合自定义 upToDateWhen 控制。
  • 并行上传:远程缓存 push 默认单线程,如需更多连接可设置:remote { isPush = true; maxParallelUploads = 4 }(需自定义缓存后端)。

4.7 常见错误与解决方案

错误表现原因解决
Could not PUT to remote build cache. Received 401 Unauthorized 凭据缺失或不正确 检查 gradle.properties 或环境变量中缓存密码;验证用户名密码是否匹配缓存服务器配置。
远程缓存始终 miss URL 错误或缓存协议不匹配 确认 URL 是否指向 Gradle 缓存 API 端点(如 /cache/);使用 curl 测试 GET/PUT 能否响应。
本地缓存项过期太快 removeUnusedEntriesAfterDays 设得太短或磁盘空间不足 增大参数或分配更多磁盘;检查其他进程是否清理了 ~/.gradle/caches/ 目录。
构建时 timeout 等待远程缓存 网络延迟高或远程服务不可用 优化连接超时参数;为 remote 缓存块添加 enabled = false 临时关闭,确保本地构建不依赖远程。

4.8 内联 SVG 结构图:buildCache 配置作用流程

buildCache 配置作用流程 (settings.gradle) settings.gradle buildCache { ... } local { ... } enabled / maxCacheSize remote { ... } url / credentials / push 启用/禁用策略 (isEnabled, isPush) 缓存后端:~/.gradle/caches 或 HTTP 服务 存储任务输出物,由输入哈希索引 提示:push 属性仅用于远程缓存;本地缓存总是允许上传新项。

4.9 生产环境部署检查清单

  1. 凭据文件隔离:将 gradle.properties 中 cachePassword 写入 CI 机密变量或不纳入版本控制。
  2. 多环境兼容:开发、CI、预发布环境下分别使用不同的缓存 URL 或禁用远程缓存,避免互相污染。
  3. 缓存可观测性:集成 org.gradle.caching.debug 并在日志中心收集缓存命中率指标。
  4. 备份与灾难恢复:远程缓存定期备份;若使用 S3/MinIO,配置跨区域复制。
  5. 持续验证:每次升级 Gradle 版本后,全量构建一次确保缓存键兼容性。

最佳实践:在 settings.gradle 顶部使用 buildCache { local { isEnabled = gradle.startParameter.isBuildCacheEnabled } } 可以让开发者通过 --no-build-cache 自由控制缓存,而远程缓存始终只读。