4. 搭建Nexus代理缓存仓库:Nexus Raw Proxy配置、Gradle仓库URL绑定
4.1 原理概述
Nexus Raw Proxy 是 Sonatype Nexus Repository 中用于代理 Maven / Gradle 依赖的核心仓库类型。在离线或受限网络环境下,它位于 Gradle 构建环境与远程公共仓库(Maven Central、Google Maven、Gradle Plugin Portal)之间,充当本地缓存代理层,避免每次构建都重复下载相同的工件。
Gradle 构建 → repositories 中配置的 Nexus Raw Proxy URL → Nexus 接收请求 → 检查本地 Blob Store 缓存 → 命中则直接返回;未命中则从上游远程仓库拉取 → 缓存到本地后返回给 Gradle。
Raw Proxy 与 Hosted(托管)仓库的关键区别在于:Raw Proxy 不存储永久副本,而是基于 LRU(最近最少使用)策略保留缓存;而 Hosted 仓库用于存放组织内部私有构件,需要手动上传或通过 CI 推送。
| 特性 | Raw Proxy(代理缓存) | Hosted(托管仓库) |
|---|---|---|
| 数据来源 | 自动从远程拉取 | 手动上传或 CI 推送 |
| 缓存策略 | LRU + TTL(可配置最大保留天数) | 永久保存,需显式删除 |
| 适用场景 | 代理 Maven Central、Google Maven 等公共仓库 | 存放组织内部二方库、SNAPSHOT 包 |
| 离线可用性 | 已缓存的工件可离线使用,未缓存则报错 | 全部可用(前提是已上传) |
4.2 实现流程
搭建 Nexus Raw Proxy 并完成 Gradle 绑定的完整流程分为 5 个步骤,从 Nexus 管理界面配置开始,到 Gradle 构建验证结束。
- 创建 Raw Proxy 仓库:在 Nexus 管理控制台新增一个
raw-proxy类型的仓库。 - 配置远程存储地址:填入上游公共仓库的 base URL(如
https://repo1.maven.org/maven2/)。 - 绑定 Blob Store:指定用于缓存工件的存储后端(建议使用独立 Blob Store 以隔离不同代理仓库的缓存)。
- 配置 Gradle 仓库 URL:将构建脚本中的
repositoriesURL 指向 Nexus Raw Proxy 的公开地址。 - 验证代理缓存:执行 Gradle 构建,观察 Nexus 的访问日志与 Blob Store 增长情况。
4.3 关键配置参数
在 Nexus 管理界面创建 Raw Proxy 仓库时,以下参数直接影响代理行为和缓存效率:
| 参数 | 推荐值 / 说明 | 作用 |
|---|---|---|
| Name | 如 maven-central-proxy | 仓库标识,Gradle 通过 URL 中的路径引用 |
| Remote Storage | https://repo1.maven.org/maven2/ | 上游远程仓库地址,支持 HTTP / HTTPS |
| Blob Store | 建议新建 maven-cache 专用 Blob Store | 缓存物理存储位置,影响磁盘 I/O 隔离性 |
| Maximum Component Age | 1440 分钟(24 小时) | 缓存有效期,超过后重新验证;离线环境可设为 -1 永不过期 |
| Maximum Metadata Age | 1440 分钟 | 元数据缓存 TTL,影响依赖解析的时效性 |
| Negative Cache TTL | 60 分钟 | 缓存不存在的工件记录,防止频繁回源请求 |
| Routing Rule | 可配置白名单 / 黑名单规则控制允许代理的路径 | 限制特定 groupId 或 artifactId 的请求 |
Maximum Component Age 设为 -1,禁止缓存过期;结合手动刷新策略,确保已缓存的依赖在断网后仍然可用。
4.4 Gradle 仓库 URL 绑定
在 Gradle 构建脚本中通过 repositories 块将依赖解析指向 Nexus Raw Proxy。绑定方式根据仓库类型分为 单一代理 和 Group 聚合 两种模式。
模式一:直接绑定单个 Raw Proxy 仓库
// build.gradle (Groovy DSL)
repositories {
maven {
url "https://nexus.internal.example.com/repository/maven-central-proxy/"
// 如需认证:
// credentials {
// username = 'deployer'
// password = 'your-password'
// }
}
maven {
url "https://nexus.internal.example.com/repository/gradle-plugin-proxy/"
}
}
模式二:绑定 Nexus Group 仓库(推荐)
通过 Nexus Group 仓库将多个 Raw Proxy 聚合到同一个 URL 下,Gradle 只需配置一个入口:
// build.gradle.kts (Kotlin DSL)
repositories {
maven {
url = uri("https://nexus.internal.example.com/repository/gradle-group/")
isAllowInsecureProtocol = false
}
}
// settings.gradle.kts (插件管理)
pluginManagement {
repositories {
maven {
url = uri("https://nexus.internal.example.com/repository/gradle-plugin-group/")
}
}
}
模式三:全局替换(init script 方案)
在 ~/.gradle/init.d/ 目录下放置 init 脚本,全局替换所有项目的仓库地址,适合团队统一管控:
// ~/.gradle/init.d/nexus-repos.gradle
allprojects {
buildscript {
repositories {
maven { url "https://nexus.intranet/repository/gradle-group/" }
}
}
repositories {
maven { url "https://nexus.intranet/repository/gradle-group/" }
}
}
4.5 调试与验证
配置完成后,通过以下命令和日志验证代理缓存是否正常工作。
步骤 1:测试 Nexus 连通性
# 使用 curl 测试 Raw Proxy 是否可访问
curl -I "https://nexus.internal.example.com/repository/maven-central-proxy/org/springframework/spring-core/5.3.30/spring-core-5.3.30.pom"
# 期望输出:HTTP/2 200 或 302(若已缓存则返回 200)
步骤 2:执行 Gradle 构建并观察缓存效果
# 第一次构建(从远程拉取并缓存)
./gradlew build --refresh-dependencies
# 第二次构建(应完全从本地缓存命中)
./gradlew build --offline
# 查看依赖解析详情
./gradlew build --info | grep "Downloaded\|Cached"
步骤 3:检查 Nexus 访问日志
# Nexus 默认日志路径
tail -f /opt/sonatype/nexus/log/request.log
# 日志示例(命中缓存时 status 为 200,且响应时间 < 10ms)
# 2025-04-09 10:15:30 [GET] /repository/maven-central-proxy/org/springframework/spring-core/5.3.30/spring-core-5.3.30.pom 200 5ms
--offline 模式构建时出现 Could not resolve external dependency 错误,说明该依赖尚未缓存到 Nexus 中。请先在联网环境下执行一次完整构建以填充缓存。
4.6 常见错误
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
Connection refused | Nexus 服务未启动或端口被防火墙拦截 | 检查 Nexus 进程状态和端口监听:netstat -tlnp | grep 8081 |
401 Unauthorized | Gradle 配置中缺少认证凭据或凭证错误 | 在 repositories 块中添加 credentials 块,或使用匿名访问(需 Nexus 开启匿名权限) |
404 Not Found | Raw Proxy 的 Remote Storage 地址配置错误 | 确认 Remote Storage 是否指向正确的上游仓库 base URL |
503 Service Unavailable | 上游远程仓库不可达(网络断开) | 检查 Nexus 服务器到外网的连通性;离线环境下确保依赖已提前缓存 |
Could not GET resource (SSL 证书错误) | Nexus 使用自签名证书导致 Gradle 拒绝连接 | 将 Nexus 证书导入 Gradle 信任库,或在 repositories 中配置 isAllowInsecureProtocol = true(仅测试环境) |
4.7 性能与稳定性优化
针对离线环境和持续集成场景,从以下维度优化 Nexus Raw Proxy 的稳定性和缓存效率:
- Blob Store 隔离:为每个 Raw Proxy 分配独立的 Blob Store,避免不同类型依赖的缓存互相干扰,也便于单独清理和迁移。
- 缓存预热脚本:在联网窗口期内,使用
wget或自定义脚本遍历项目的gradle-dependencies.xml或pom.xml,强制 Nexus 缓存所有关键依赖:
#!/bin/bash
# cache-warmup.sh — 批量预热 Gradle 依赖到 Nexus Raw Proxy
BASE_URL="https://nexus.intranet/repository/maven-central-proxy"
DEP_LIST="dependencies.txt" # 每行一个 Maven 坐标: group:artifact:version
while IFS= read -r coord; do
# 将 group:artifact:version 转换为路径
group=$(echo "$coord" | cut -d: -f1 | tr '.' '/')
artifact=$(echo "$coord" | cut -d: -f2)
version=$(echo "$coord" | cut -d: -f3)
url="${BASE_URL}/${group}/${artifact}/${version}/${artifact}-${version}.pom"
echo "Warming: $url"
curl -s -o /dev/null -w "%{http_code}\n" "$url"
done < "$DEP_LIST"
- Negative Cache 调优:将
Negative Cache TTL从默认的 60 分钟提升到 1440 分钟(24 小时),减少重复查询不存在的工件。 - 磁盘监控与清理:配置 Blob Store 的
Soft Quota限制最大缓存容量(如 50 GB),当磁盘使用率超过阈值时自动触发 Compact Blob Store 任务释放空间。 - 高可用部署:在集群环境中使用 Nexus 实例 + 共享 NFS 存储,或启用 Nexus 自带的 High Availability 模式,避免单点故障导致整个 CI 流水线阻塞。
./gradlew build --offline 验证 全部依赖从 Nexus 缓存命中,零外网请求。如命中率低于 95%,建议使用 --refresh-dependencies 模式补全缓存。