第1章 离线环境规划与缓存目录设计
离线构建的核心挑战在于如何在无网络条件下精确、高效地管理依赖缓存。本章将引导你设计一套结构清晰、支持多仓库隔离、可适配不同存储介质的离线缓存目录体系。
1.1 缓存总目录结构
Gradle 默认缓存位于 ~/.gradle/caches,但离线环境下需要独立且可迁移的目录。推荐采用层次化目录结构:
offline-cache/
├── metadata/ # 仓库元数据索引
│ ├── maven-central/
│ ├── jcenter/
│ └── custom-repo/
├── modules/ # 实际依赖模块
│ ├── maven-central/
│ ├── jcenter/
│ └── custom-repo/
├── transforms/ # 构建转换缓存
├── native/ # 本地库缓存
└── config.properties # 缓存配置
1.2 分仓隔离策略
多仓库共存时,若混放可能导致坐标冲突或版本混乱。分仓隔离通过为每个仓库分配独立子目录,避免命名冲突,同时便于按仓库逐批更新。
具体实现方案:
- 仓库标识化:使用仓库 URL 的哈希或简化名称作为子目录名。
- 层级映射:每个仓库内部按
group/artifact/version/三级存储。 - 元数据独立:
metadata/子目录存放该仓库的maven-metadata.xml等索引文件。
| 仓库类型 | 子目录示例 | 备注 |
|---|---|---|
| Maven Central | modules/maven-central/ | 官方仓库 |
| JCenter | modules/jcenter/ | 已停用,示例保留 |
| 私有 Nexus | modules/nexus-mycompany/ | 企业内网 |
| 本地 file repo | modules/local-libs/ | 本地目录 |
设计要点:分仓隔离简化了权限控制和同步策略。例如仅对
modules/nexus-mycompany/ 目录设置只读,防止意外覆盖。1.3 存储介质选择与影响
缓存读写性能直接受存储介质影响。下表对比常见媒介:
| 介质 | 顺序读写 | 随机读写 | 容量 | 推荐场景 |
|---|---|---|---|---|
| NVMe SSD | 极高 | 极高 | 256GB~2TB | 核心开发机 |
| SATA SSD | 高 | 中 | 120GB~1TB | CI 节点 |
| HDD | 低 | 低 | 1TB~10TB | 冷存储备份 |
| NFS | 中(网络决定) | 低 | 共享 | 团队共享缓存 |
性能警告:NFS 在大量小文件操作(如 Gradle 解压 JAR)时延迟显著。若必须使用,确保挂载参数
noatime、nodiratime,并开启 actimeo=30 减少属性查询。1.4 实现流程:搭建离线缓存目录
- 创建根目录:
mkdir -p /opt/gradle-offline-cache - 按分仓隔离原则建立子目录:
mkdir -p /opt/gradle-offline-cache/{metadata,modules,transforms,native}
mkdir -p /opt/gradle-offline-cache/metadata/maven-central
mkdir -p /opt/gradle-offline-cache/modules/maven-central
- 创建配置文件(YAML 或 Properties):
# /opt/gradle-offline-cache/config.properties
cache.base=/opt/gradle-offline-cache
repo.isolation=true
repo.maven-central.url=https://repo1.maven.org/maven2
repo.jcenter.url=https://jcenter.bintray.com
# 若使用 NFS,可指定
cache.fs.noatime=true
- 验证目录结构:
tree /opt/gradle-offline-cache -L 2
1.5 目录结构示意图
1.6 调试与验证
使用 Gradle 命令行指定缓存目录进行测试:
gradle build --offline --cache-dir /opt/gradle-offline-cache --no-daemon --info 2>&1 | grep -i "cache"
若发现依赖缺失,检查:
- 缓存目录是否存在对应坐标路径?
config.properties中的repo.isolation是否开启?- 存储介质的磁盘空间是否充足?
1.7 常见错误与性能优化
常见错误:
- “Could not resolve all dependencies” — 缓存目录未正确挂载或分仓子目录缺失。
- NFS 挂载后构建缓慢 — 检查
actimeo和noatime挂载参数。 - Permission denied — 缓存目录权限不足,建议使用
chmod -R 755。
性能优化:
- 优先使用本地 NVMe SSD 作为主缓存,HDD 或 NFS 仅用于备份。
- 启用 Gradle 的
--parallel和--max-workers并行解压。 - 定期清理过期依赖(
gradle cleanBuildCache或手动删除metadata/下冗余索引)。 - 为 NFS 启用缓存代理(如
cachefilesd)减少网络往返。