Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/zhenye-na/pan.go
💾 A Tiny Golang based Distributed Cloud Storage Service | MySQL, Reids, RabbitMQ, Docker and Ceph
https://github.com/zhenye-na/pan.go
aliyun-oss ceph docker golang grpc-go k8s mysql rabbitmq redis
Last synced: 17 days ago
JSON representation
💾 A Tiny Golang based Distributed Cloud Storage Service | MySQL, Reids, RabbitMQ, Docker and Ceph
- Host: GitHub
- URL: https://github.com/zhenye-na/pan.go
- Owner: Zhenye-Na
- License: mit
- Created: 2019-11-18T06:48:48.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2020-04-02T01:29:37.000Z (over 4 years ago)
- Last Synced: 2023-03-01T11:05:35.574Z (over 1 year ago)
- Topics: aliyun-oss, ceph, docker, golang, grpc-go, k8s, mysql, rabbitmq, redis
- Language: Go
- Homepage:
- Size: 4.2 MB
- Stars: 4
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# pan.go
## 1. 使用
### 1.1. 安装外部库
```bash
go get github.com/garyburd/redigo/redis
go get github.com/go-sql-driver/mysql
go get github.com/garyburd/redigo/redis
go get github.com/json-iterator/go
go get github.com/aliyun/aliyun-oss-go-sdk/oss
go get gopkg.in/amz.v1/aws
go get gopkg.in/amz.v1/s3
go get github.com/streadway/amqp
```### 1.2. 启动服务
#### 1.2.1. 在加入 RabbitMQ 实现文件异步转移之前
启动上传应用程序:
```bash
$ cd $GOPATH/pan.go
$ go run main.go
```#### 1.2.2. 在加入 RabbitMQ 实现文件异步转移阶段, 启动方式 (分裂成了两个独立程序):
启动**上传**应用程序:
```bash
$ cd $GOPATH/pan.go
$ go run service/upload/main.go
```启动**转移**应用程序:
```bash
$ cd $GOPATH/pan.go
$ go run service/transfer/main.go
```打开 `localhost:8080` 端口查看
```
http://localhost:8080
```## 2. 项目支持的功能
* [x] 简单的文件上传服务
* [x] MySQL 存储文件元数据
* [x] 账号系统, 注册/登录/查询用户或文件数据
* [x] 基于帐号的文件操作接口
* [x] 文件秒传功能
* [x] 文件分块上传/断点续传功能
* [x] 搭建及使用 Ceph 对象存储集群
* [x] 使用阿里云 OSS 对象存储服务
* [x] 使用 RabbitMQ 实现异步任务队列
* [ ] 微服务化 (API网关, 服务注册, RPC通讯)
* [ ] CI/CD (持续集成)## 3. 详细介绍
### 3.1. 项目架构组成
mermaid 流程图代码:
```mermaid
graph TDB[服务发现] --> |获取| A[上传调度]
D((用户)) --> |请求上传| C[API 网关] --> |获取上传节点地址| A[上传调度]
D((用户)) --> |实际上传| F([上传服务集群])
F[上传服务集群] --> |推送转移任务| G([消息队列 MQ]) --> |获取转移任务| H([转移服务集群])
H([转移服务集群]) & E[配置中心] & F([上传服务集群]) --> |注册| B[服务发现]
F[上传服务集群] --> |文件 Meta / 分块 Meta / 秒传| I([DB Proxy])
I([DB Proxy]) --> |分块 Meta| J[(Redis)]
I([DB Proxy]) --> |文件 Meta| K[(MySQL)]
H([转移服务集群]) --> |更新文件 Meta| I([DB Proxy])
H([转移服务集群]) --> |写 OSS| L[(OSS)]
H([转移服务集群]) --> |写 Ceph| M[(Ceph)]
```### 3.2. 基于 MySQL 的文件数据库
MySQL 主要用作两个数据库
- 用户表
- 文件表备用字段的目的是:
1. 安全性. 避免在物理层面删除数据所造成的数据丢失
2. 减少文件删除所生成的文件碎片```sql
CREATE TABLE `tbl_file` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`file_sha1` char(40) NOT NULL DEFAULT '' COMMENT '文件hash',
`file_name` varchar(256) NOT NULL DEFAULT '' COMMENT '文件名',
`file_size` bigint(20) DEFAULT '0' COMMENT '文件大小',
`file_addr` varchar(1024) NOT NULL DEFAULT '' COMMENT '文件存储位置',
`create_at` datetime default NOW() COMMENT '创建日期',
`update_at` datetime default NOW() on update current_timestamp() COMMENT '更新日期',
`status` int(11) NOT NULL DEFAULT '0' COMMENT '状态(可用/禁用/已删除等状态)',
`ext1` int(11) DEFAULT '0' COMMENT '备用字段1',
`ext2` text COMMENT '备用字段2',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_file_hash` (`file_sha1`),
KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```当文件存储数量开始变多后, 我们需要考虑**分库分表**
- 通过 `sql.DB` 来管理连接数据库对象
- 通过 `sql.Open` 来创建**协程**安全的 `sql.DB` 对象
- 优先使用 Prepared Statement
- 有效防止 SQL 注入攻击
- 实现自定义参数查询, 提高效率### 3.3. 用户系统 - 资源隔离及鉴权
创建用户表结构
```sql
CREATE TABLE `tbl_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_name` varchar(64) NOT NULL DEFAULT '' COMMENT '用户名',
`user_pwd` varchar(256) NOT NULL DEFAULT '' COMMENT '用户encoded密码',
`email` varchar(64) DEFAULT '' COMMENT '邮箱',
`phone` varchar(128) DEFAULT '' COMMENT '手机号',
`email_validated` tinyint(1) DEFAULT 0 COMMENT '邮箱是否已验证',
`phone_validated` tinyint(1) DEFAULT 0 COMMENT '手机号是否已验证',
`signup_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '注册日期',
`last_active` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后活跃时间戳',
`profile` text COMMENT '用户属性',
`status` int(11) NOT NULL DEFAULT '0' COMMENT '账户状态(启用/禁用/锁定/标记删除等)',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`user_name`),
KEY `idx_status` (`status`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4;
```用户登陆之后, 会自动生成 token 方便下次登录, 所以我们创建一个新的表, 用来存储生成的 token
```sql
CREATE TABLE `tbl_user_token` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_name` varchar(64) NOT NULL DEFAULT '' COMMENT '用户名',
`user_token` char(40) NOT NULL DEFAULT '' COMMENT '用户登录token',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`user_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```**用户系统的一些接口的实现逻辑:**
_用户注册功能_
1. `HTTP GET` 请求, 返回登录页面的内容
2. 校验参数的有效性
3. 加密用户名和密码
4. 存入数据库并且返回结果_用户登录_
1. 校验用户名和密码
2. 生成访问凭证
3. 存储 token 到数据库_用户查询_
1. 解析请求参数
2. 验证 token 是否过期/有效
3. 查询用户信息
4. 响应用户数据### 3.4. 基于 Hash 算法实现文件秒传
秒传原理以及应用
1. 用户上传 - 体积很大的文件也可以瞬间完成, 其他用户也上传过相同文件 (文件校验算法相同结果)
2. 离线下载
3. 好友分享所以根据以上, 为了实现秒传
- 文件 Hash (MD5, SHA1 等)
- 用户/文件关联
我们定义一个 "用户-文件表" 来存储上传的文件所属信息
```sql
CREATE TABLE `tbl_user_file` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`user_name` varchar(64) NOT NULL,
`file_sha1` varchar(64) NOT NULL DEFAULT '' COMMENT '文件hash',
`file_size` bigint(20) DEFAULT '0' COMMENT '文件大小',
`file_name` varchar(256) NOT NULL DEFAULT '' COMMENT '文件名',
`upload_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '上传时间',
`last_update` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
`status` int(11) NOT NULL DEFAULT '0' COMMENT '文件状态(0正常1已删除2禁用)',
UNIQUE KEY `idx_user_file` (`user_name`, `file_sha1`),
KEY `idx_status` (`status`),
KEY `idx_user_id` (`user_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```那么我们怎么实现秒传判断的接口呢?
1. 首先解析传入的参数
2. 然后在文件表中查询是否存在相同的文件 Hash 值
3. 如果不存在, 那么秒传失败
4. 如果查询成功, 那么写入用户-文件表, 更新信息, 并且返回 "秒传成功"针对相同的文件(文件加密后 sha1 值相同)
- 允许不同用户上传同一个文件
- 先完成上传的先被存入数据库
- 后上传的只会更新"用户-文件表", 完成后会删除文件### 3.5. 基于 Redis 实现分块上传及断点续传
**分块上传**
文件切分成多块, 独立传输, 上传后合并文件
**断点续传**
传输暂停或者出现异常中断后, 可以基于原来的进度继续
**说明**
1. 小文件不需要进行分块上传, 因为分块上传接口更复杂
2. 可以并行分块上传, 并且可以无序传输
3. 提高传输速率
4. 减少失败后重试的时间和流量### 3.6. 基于 Ceph 搭建私有云存储服务
Ceph 基础组件
1. OSD: 用于集群中所有数据与对象的存储, 存储/复制/平衡/恢复数据等等
2. Monitor: 监控集群状态, 维护 Cluster MAP 表, 保证集群数据一致性
3. MDS: 保存文件系统服务的元数据 (OBJ/Block 不需要该服务)
4. GW: 提供与 Amazon S3 和 Swift 兼容的 RESTful API 的 GateWay 服务### 3.7. 阿里云OSS实现海量数据上云
略
### 3.8. 基于 RabbitMQ 实现异步存储
#### 异步逻辑的实现
mermaid 流程图代码
```
graph LR
B[客户端] --> A[上传服务]
A[上传服务] --> B[客户端]
A[上传服务] --> C[临时存储] & D[任务队列] -.-> E[转移服务]
E[转移服务] -.-> F[OSS]
F[OSS] -.-> E[转移服务]
```#### Rabbit MQ 可以解决什么
1. 逻辑解耦, 异步任务
2. 支持消息持久化, 重启服务不会受到影响
3. 削峰, 大规模消息处理#### Exchange 工作模式
- Fanout: 类似**广播**, 转发到所有绑定交换机的 Queue
- Direct: 类似**单播**, RoutingKey 和 BindingKey 完全匹配
- Topic: 类似**组播**, 转发到符合通配符匹配的 Queue
- Headers: 请求头与消息头匹配, 才能接受消息| ![](./doc/fanout.png) | ![](./doc/direct.png) |
|----------------------- |----------------------- |
| 工作模式 - Fanout | 工作模式 - Direct |
| ![](./doc/topic.png) | |
| 工作模式 - Topic | |### 3.9. 架构微服务化
#### 3.9.1. 微服务的概念以及原理
微服务的优点:
1. 化繁为简, 分散治理
2. 服务间松耦合, 服务内高内聚
3. 服务科独立构建/部署/升级, 局部更新
4. 提高系统容错性, 减少系统整体崩溃概率
5. 易于实现异构系统微服务的缺点:
1. 增加了运维部署的工作量与难度
2. 增加了系统间调用逻辑的处理难度
3. 日志更难收集和统计了
4. 额外引入了一些非业务模块服务### 3.10. Docker & K8s 容器化实战
#### 3.10.1. Docker
Docker 可以做到:
1. 限制容器 CPU 以及内存的资源消耗
2. 依赖环境隔离
3. 快速扩容, 动态起停容器实例在这里喔们要用到 Docker 的一个工具 `Compose`, 使用 `docker-compose.yml` 进行编写. 是一个进行容器编排的工具
主要步骤拆解:
1. 通过 `Dockerfile` 定义容器环境, 打包成镜像
2. 通过 `docker-compose.yml` 定义各个应用服务```bash
$ sudo docker-compose up --scale upload=2 --scale download=2 -d
```#### 3.10.2. Kubernetes
K8s 是一个分布式系统支撑平台
1. 底层可以基于 Docker 来包装应用
2. 以集群的方式来运行/管理跨机器的容器应用
3. 解决了 Docker 跨机器场景的容器通讯问题
4. 拥有自动修复能力提供部署运行/资源调度/服务发现/动态伸缩等一系列功能
### 4. 总结
![](./doc/keypoints.png)
![](./doc/skillsets.png)
## 参考资料
- Go入门: [语言之旅](https://tour.go-zh.org/welcome/1)
- MySQL: [偶然翻到的一位大牛翻译的使用手册](https://chhy2009.github.io/document/mysql-reference-manual.pdf)
- Redis: [命令手册](http://redisdoc.com/)
- Ceph: [中文社区](http://ceph.org.cn/) [中文文档](http://docs.ceph.org.cn/)
- RabbitMQ: [英文官方](http://www.rabbitmq.com/getstarted.html) [一个中文版文档](http://rabbitmq.mr-ping.com/)
- 阿里云OSS: [文档首页](https://help.aliyun.com/product/31815.html?spm=a2c4g.750001.3.1.47287b13LQI3Ah)
- gRPC: [官方文档中文版](http://doc.oschina.net/grpc?t=56831)
- k8s: [中文社区](https://www.kubernetes.org.cn/docs)* * *
Icons made by Freepik from www.flaticon.com