一、为什么需要 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]

这种开发模式的工程保障:

  1. 独立的兼容性测试模块compat-test 面向真实 Nexus 实例做黑盒测试
  2. 协议行为对比:HTTP 状态码、Header、响应体语义、checksum 全量对比
  3. 迁移可验证:preflight、resume、retry、checksum 校验和报告
  4. 多副本状态落盘:默认要求落 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 支持进一步扩大了其适用场景。

参考来源

  1. 腾讯云开发者社区(kl博主), nexus-plus 更名为 kkRepo 继续开源, 2026-06-26 — 原文链接
  2. V2EX, Nexus 的平替 nexus-plus 开源涉嫌商标侵权,被迫改名 kkRepo, 2026 — 原文链接
  3. 阿里云开发者社区, 使用 kkRepo 搭建 Maven 私服, 2026 — 原文链接