一、为什么需要 kkRepo
Sonatype Nexus Repository 是 Java 生态中最流行的制品仓库,但随着使用规模扩大,几个痛点日益明显:
- 架构老旧:依赖 OrientDB、内嵌 Elasticsearch,升级和恢复风险高
- 开源版受限:免费版本加了大量限制,PRO 版本价格昂贵
- 高可用困难:不支持原生多副本部署,横向扩容受限
- 存储绑定:blob 数据绑定本地目录,不适合云原生和对象存储架构
kkRepo 应运而生——一个完全开源(Apache 2.0)、兼容 Nexus 客户端协议、但运行时架构全面云原生的自托管制品仓库。[1]
二、核心架构对比
2.1 kkRepo vs Nexus 架构差异
| 维度 | Sonatype Nexus | kkRepo |
|---|---|---|
| 元数据存储 | OrientDB / H2 | MySQL(生产级、可备份) |
| Blob 存储 | 本地文件系统 | OSS/S3 对象存储(可横向扩展) |
| 部署形态 | 单节点为主 | 原生多副本,无状态设计 |
| 协议兼容 | 自有协议 | 兼容 Nexus /repository/<repo>/... URL 布局 |
| 弹性扩容 | 困难 | Kubernetes / ECS 友好 |
| 迁移能力 | 手动脚本 | 可视化、可续跑、可重试的迁移流程 |
| AI 开发 | 传统开发 | 主体代码由 AI 编程助手完成 |
2.2 运行时架构
┌─────────────────────────────────────────────────────────────┐
│ Load Balancer │
│ (Nginx / K8s Ingress) │
└───────────────────────┬─────────────────────────────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ kkRepo │ │ kkRepo │ │ kkRepo │
│ Instance 1 │ │ Instance 2 │ │ Instance 3 │
│ (无状态) │ │ (无状态) │ │ (无状态) │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
└────────────────┼────────────────┘
│
┌────────────────┼────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ MySQL │ │ Redis │ │ OSS/S3 │
│ (元数据/权限 │ │ (Session/ │ │ (Blob 存储 │
│ /审计/迁移) │ │ 缓存/协同) │ │ /大文件) │
└──────────────┘ └──────────────┘ └──────────────┘
关键设计原则:
- 任意应用副本都可以处理仓库请求,正确性不依赖单个 JVM 的内存状态
- 进程内缓存丢失后可自动回暖
- blob 内容在 OSS/S3 中,应用节点不需要绑定持久化本地磁盘
三、v0.3.0 新特性详解
3.1 UI 全新升级
v0.3.0 对管理控制台进行了全面重构:
- 现代化的响应式 UI,基于 Vue 3 + Element Plus
- 仓库浏览支持表格、卡片、树形多种视图
- 迁移任务可视化进度追踪
- 审计日志支持时间线视图和高级筛选
3.2 新增 Dart / Pub 私服支持
Flutter / Dart 生态在国内增长迅速,但 pub.dev 的访问不稳定。kkRepo v0.3.0 新增了对 Pub 仓库协议的完整支持:
# Flutter 项目 pubspec.yaml
name: my_flutter_app
dependencies:
http: ^1.0.0
provider: ^6.0.0
# 配置 kkRepo 作为 Pub 镜像
dependency_overrides:
# 通过环境变量或命令行指定
# 设置 Pub 环境变量指向 kkRepo
export PUB_HOSTED_URL="https://your-kkrepo.example.com/repository/pub/"
# 或使用 Flutter 的 pub 命令
flutter pub get
kkRepo 的 Pub 支持包括:
- 完整兼容 Pub API(package listing、version resolution、archive download)
- 支持代理 pub.dev 并本地缓存
- 支持托管私有 Dart 包
- 与 kkRepo 统一的权限和审计体系
3.3 更多仓库格式支持
v0.3.0 支持的制品格式已扩展至:
| 格式 | 类型 | 状态 |
|---|---|---|
| Maven | Java/Scala/Kotlin | 完整支持 |
| npm | JavaScript/Node.js | 完整支持 |
| PyPI | Python | 完整支持 |
| Go Module Proxy | Go | 完整支持 |
| Helm | Kubernetes | 完整支持 |
| Docker / OCI | 容器镜像 | 完整支持 |
| NuGet | .NET | 完整支持 |
| RubyGems | Ruby | 完整支持 |
| Yum | RPM 包 | 完整支持 |
| Raw | 通用文件 | 完整支持 |
| Pub / Dart | Flutter | v0.3.0 新增 |
路线图中的未来支持:APT / Debian、Cargo / Rust、Terraform Provider、Conan、Conda、Composer
四、迁移指南:从 Nexus 到 kkRepo
4.1 迁移前准备
# 1. 确认源 Nexus 版本和配置
curl -u admin:admin123 http://nexus.example.com/service/rest/v1/status
# 2. 备份 Nexus 数据(必须!)
# 按照 Nexus 官方文档执行完整备份
# 3. 部署 kkRepo(Docker Compose 示例)
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
kkrepo:
image: klboke/kkrepo:latest
ports:
- "19090:19090"
- "19091:19091"
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/kkrepo
- SPRING_DATASOURCE_USERNAME=kkrepo
- SPRING_DATASOURCE_PASSWORD=your_password
- STORAGE_OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com
- STORAGE_OSS_BUCKET=kkrepo-blobs
depends_on:
- mysql
- redis
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root_password
MYSQL_DATABASE: kkrepo
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
volumes:
mysql_data:
redis_data:
EOF
docker-compose up -d
4.2 执行迁移
# kkRepo 管理后台提供可视化迁移向导
# 1. 配置源 Nexus 地址和凭据
# 2. 执行 Preflight 检查
# 3. 迁移用户、角色、权限
# 4. 迁移仓库定义和 blob store 配置
# 5. 执行资产数据迁移(支持断点续传)
# 6. 增量同步(上线前最后一次同步)
# 7. 切换域名指向 kkRepo
4.3 客户端零改动迁移
kkRepo 最大的优势是客户端配置无需修改。以 Maven 为例:
<!-- 原来的 settings.xml -->
<settings>
<servers>
<server>
<id>releases</id>
<username>deployer</username>
<password>***</password>
</server>
</servers>
<mirrors>
<mirror>
<id>central</id>
<url>http://nexus.example.com/repository/maven-public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
</settings>
域名切换后,同样的 settings.xml 直接指向 kkRepo 即可正常工作,所有构建任务无需修改。
五、性能对比
基于社区测试和内部数据,kkRepo 在关键场景下的表现:
| 指标 | Nexus OSS (单节点) | kkRepo (3 副本) |
|---|---|---|
| 并发下载 (1000 请求) | 请求排队,部分超时 | 均匀分发,全部成功 |
| 故障恢复 | 需手动恢复 OrientDB | 副本自动剔除,流量自动切换 |
| 存储扩容 | 停机迁移数据目录 | 对象存储自动扩展,零停机 |
| 升级部署 | 停机维护窗口 | 滚动升级,零停机 |
| 元数据查询 (10万组件) | ~2s | ~200ms (MySQL 索引优化) |
| 内存占用 | 4-8GB (JVM + OrientDB) | 2-4GB (纯 JVM,无内嵌 DB) |
六、AI 辅助开发的工程实践
kkRepo 的一个独特之处在于:主体代码由 AI 编程助手完成,人负责架构边界、兼容性要求和 Review。[1]
这种开发模式的工程保障:
- 独立的兼容性测试模块:
compat-test面向真实 Nexus 实例做黑盒测试 - 协议行为对比:HTTP 状态码、Header、响应体语义、checksum 全量对比
- 迁移可验证:preflight、resume、retry、checksum 校验和报告
- 多副本状态落盘:默认要求落 MySQL,进程内缓存仅作为可恢复优化
// compat-test 示例:验证 Maven 元数据响应一致性
@Test
public void testMavenMetadataResponse() {
Response nexusResponse = callNexus("/repository/maven-public/com/example/lib/maven-metadata.xml");
Response kkrepoResponse = callKkRepo("/repository/maven-public/com/example/lib/maven-metadata.xml");
assertEquals(nexusResponse.status(), kkrepoResponse.status());
assertEquals(nexusResponse.header("Content-Type"), kkrepoResponse.header("Content-Type"));
assertXmlEquivalent(nexusResponse.body(), kkrepoResponse.body());
}
总结:kkRepo 不是"重新发明 Nexus",而是为需要迁移、需要多副本、需要 MySQL + OSS/S3 架构的团队,提供一个更简单、更可控、更容易恢复的开源选择。v0.3.0 的 UI 升级和 Dart/Pub 支持进一步扩大了其适用场景。
浙公网安备 33010602011771号