S3 兼容对象存储服务,基于 Spring Cloud Alibaba 微服务架构。支持多存储后端(MinIO / 本地 / 阿里云 OSS)、秒传、分片上传、回收站,Gateway 全链路非阻塞,9 项 JMeter 基准测试验证。
StorageBackend 接口NORMAL → RECYCLED(30天)→ DELETED 状态机,XXL-Job 每天凌晨 3 点自动清理过期对象RedissonReactiveClient,避免 Netty event loop 被 Redis 同步操作阻塞,尖峰 2,000 并发 0 错误HotKeyUtil 3-shard hash-tag 分布,读写均分到 3 个 master 节点,偏差 < 20%object_info 按 bucket_id % 2 分片 ┌──────────────────────────────────────────┐
│ Spring Cloud Gateway (38080) │
│ Nacos 服务发现 + Sentinel 流控 + JWT 鉴权 │
└──────┬────────────────────┬─────────────┘
│ │
┌──────────▼──────────┐ ┌───────▼──────────┐
│ object-storage │ │ object-metadata │
│ (38081) │ │ (38082) │
│ 数据面 / IO 密集型 │ │ 控制面 / CPU 密集型 │
│ ┌───────────────┐ │ │ ┌────────────┐ │
│ │StorageBackend │ │ │ │ MySQL │ │
│ │ MinIO/本地/OSS │ │ │ │ (元数据) │ │
│ └───────────────┘ │ │ └────────────┘ │
│ ┌───────────────┐ │ │ ┌────────────┐ │
│ │Redis Cluster │ │ │ │ Redis │ │
│ │(秒传/分片状态) │ │ │ │ Cluster │ │
│ └───────────────┘ │ │ │ (缓存) │ │
│ ┌───────────────┐ │ │ └────────────┘ │
│ │ RabbitMQ │──┼─┼──▶ 消费者 │
│ │ (Outbox) │ │ │ │
│ └───────────────┘ │ │ │
└─────────────────────┘ └──────────────────┘
基础设施: Nacos(38848) Sentinel(38858) MySQL(33306/33307)
Redis Cluster(37000-37005) RabbitMQ(35672) MinIO(39000/39001) XXL-Job(39080)
| 模块 | 角色 | 核心技术 |
|---|---|---|
gateway |
API 网关 | Spring Cloud Gateway + JWT + Sentinel + RedissonReactiveClient |
object-storage |
数据面 | StorageBackend (MinIO/Local/OSS) + Redis + RabbitMQ Outbox |
object-metadata |
控制面 | MySQL + MyBatis-Plus + Redis Cache + RabbitMQ Consumer |
admin-ui |
管理后台 | React 19 + Vite + shadcn/ui + i18n |
common |
公共库 | DTO、S3ErrorCode 异常枚举、StorageBackend 接口、HotKeyUtil |
| 我的文件 | Bucket 文件浏览 |
|---|---|
![]() |
![]() |
git clone https://github.com/<org>/cloud-disk.git
cd cloud-disk
echo "JAVA_HOME=/path/to/jdk-21" > .env
make package-fast
docker compose up -d
首次启动约 2-3 分钟,等待所有容器 healthy:
docker compose ps
curl -s -w "\nHTTP:%{http_code}" -X POST http://localhost:38080/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"123456"}'
| 控制台 | 地址 | 默认凭证 |
|---|---|---|
| Nacos 注册中心 | http://localhost:38848/nacos | nacos / nacos |
| MinIO 对象存储 | http://localhost:39001 | minioadmin / minioadmin |
| RabbitMQ 消息队列 | http://localhost:45672 | admin / admin123 |
| Sentinel 流控 | http://localhost:38858 | sentinel / sentinel |
| XXL-Job 定时任务 | http://localhost:39080/xxl-job-admin | admin / 123456 |
| Admin UI | http://localhost:5173 | admin / 123456 |
所有请求通过 Gateway (http://localhost:38080) 转发。完整 API 文档:docs/deployment.md
TOKEN="<从 /login 获取>"
# 创建 Bucket
curl -X PUT http://localhost:38080/my-bucket \
-H "Authorization: Bearer $TOKEN"
# 上传对象
curl -X PUT http://localhost:38080/my-bucket/hello.txt \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: text/plain" \
-d "Hello World!"
# 秒传(携带 MD5,命中则跳过实际上传)
MD5=$(md5sum large-file.bin | cut -d' ' -f1)
curl -X PUT http://localhost:38080/my-bucket/large-file.bin \
-H "Authorization: Bearer $TOKEN" \
-H "x-cloud-disk-md5: $MD5" \
-T large-file.bin
# 秒传命中时返回: { "data": { "instant": true } }
# 下载对象(默认 302 跳转至预签名 URL,-L 跟随重定向)
curl -L -X GET http://localhost:38080/my-bucket/hello.txt \
-H "Authorization: Bearer $TOKEN" -o hello.txt
# 强制代理模式(数据流经 Gateway)
curl -X GET "http://localhost:38080/my-bucket/hello.txt?proxy=true" \
-H "Authorization: Bearer $TOKEN" -o hello.txt
# 列举对象 (S3 ListObjectsV2)
curl "http://localhost:38080/my-bucket?list-type=2&prefix=images/" \
-H "Authorization: Bearer $TOKEN"
| 功能 | 支持 |
|---|---|
| PUT / DELETE / HEAD Bucket | Y |
| GET Bucket (ListObjectsV2) | Y |
| PUT / GET / HEAD / DELETE Object | Y |
| Delete Multiple Objects | Y |
| CopyObject | Y |
| Multipart Upload (Init / Part / Complete / Abort) | Y |
| List Parts | Y |
| Pre-signed URL | Y |
| Bucket Policy / Object Lock / Versioning | N |
| 文档 | 内容 |
|---|---|
| docs/architecture.md | 架构设计、数据流、数据库设计、关键设计决策 |
| docs/deployment.md | 部署手册、配置参考、完整 API 文档、故障排查 |
| docs/development.md | 开发环境、项目结构、编码规范、测试指南 |
| docs/nacos-config.md | Nacos 动态配置 Sentinel 流控规则 |
| benchmark/README.md | JMeter 基准测试套件(9 项测试,尖峰 2,000 并发 0 错误) |