以下是该项目的笔记,随手记录,仅供参考
项目主要做什么?
- 基于 Golang 实现分布式文件上传服务系统
- 结合开源存储 Ceph 公有云(阿里OSS)、支持断点续传及秒传功能
- 微服务化及容器部署
项目收获
- Redis / RabbitMQ ,结合缓存服务,rabbitMQ将同步逻辑转换成异步来执行,服务只需要往MQ发送数据就行,不需要关心具体是谁来消费提交的任务
- Docker / Kubernets 进行部署
- 分布式对象存储Ceph
- 阿里云 OSS 对象存储服务
收获那些?
- 文件分块断点上传 & 秒传
- 了解对象从 Ceph 迁移到阿里云 OSS的经验
主要接口:
接口描述 | 接口URL |
---|---|
上传 | POST /file/upload |
查询 | GET /file/query |
下载 | GET /file/download |
删除 | POST /file/delete |
修改 | POST /file/update |
思考?上传文件后,如果需要去查询,怎么查?关键点是,需要每次上传的文件内容记录下来作为文件唯一标志,唯一标志一般我们使用 hash 、sha1、md5这些,记录比如文件ID、文件名、上传时间、文件大小、存储的路径等等都要保留下来。这样方便在查询时,把这些信息返回给用户。
如何记录下来呢,怎么实现?定义一个结构体来存储即可。
上面我们是把文件上传后存储到本地内存的,这样关闭服务就没有了,我们需要将文件存储到MySQL中。
MySQL 采用主从集群,master 和 slave
数据库表是如何设计的?
文件表:filesha1,filename.filesize,file_adder,create_at创建时间,update_at文件更新时间,status状态
Go 操作MySQL
- 在Go访问数据库,通过sql.DB来管理数据库连接对象
- 通过sql.Open 来创建协程安全的sql.DB对象(一般是长连接的,不需要每次调用Open方法)
- 优先使用 prepared statement 可以防止sql注入
支持用户注册与登录 在DB模块新加一个用户注册方法,也就是往MySQL的用户表插入使用一条新的记录
登录接口,需要生成访问凭证,我们也将token存在数据库token表中
总结:
-
用户注册接口逻辑
-
(1)判断请求是否为get请求,直接返回注册页面;反之执行下一步
-
(2)校验参数是否有效(用户名长度及密码是否有非法)
-
(3)加密用户密码
-
(4)将用户名密码等存入数据库tbl_user表及返回结果
-
-
用户登录接口
-
(1)校验用户名及密码
-
(2)生成访问凭证(token)
-
(3)存储 token 到数据库 tbl_user_token 表
-
(4)返回 username,token,重定向URL等信息
-
-
用户信息查询接口
-
(1)解析请求参数
-
(2)验证token是否有效
-
(3)查询用户信息
-
(4)组装并且响应用户数据
-
-
拦截器验证 token
-
首先获取 username 和 token
-
然后判断 token 是否有效,无效直接返回错误信息给客户端
-
有效的话,传递到具体的handle函数中进行逻辑处理
-
1、妙传原理:首先用户上传文件,然后上传server接受到数据流之后,它会一边将数据存到本地,一边通知hash计算模块 通过它计算当前文件内容的哈希值,等整个文件上传完成之后,就会得到整个文件的哈希值,上传server将哈希值写入到唯一文件表, 最后,将文件元信息关联到用户文件表里面,下次查询时通过用户文件表进行查询,如果发送秒传情况下,直接将用户元信息关联到用户文件表里面
2、场景:
(1)用户上传
(2)离线下载
(3)好友分享
3、关键点:
(1)记录每个文件的 hash 值,一般使用MD5或SHA1等计算,这样用户下一次上传文件时,只要哈希相同,可以省去重复上传
(2)用户文件关联
4、数据库设计,有用户文件表
5、总结
-
Hash 算法的应用场景与对比
-
秒传的原理和简单实现:其实就是后端做了文件的共享,相同内容的文件只会上传一份,同时也只会保持一份
(1)概念
-
分快上传:文件切成多块,独立传输、上传完成后合并
-
断点续传:基于分块上传实现的,传输暂停或异常中断后,可基于原来进度重传
-
分块说明:对于小文件不建议分块上传;可并行上传分块,且无序传输;减少传输失败重试的流量及时间
(2)实现说明:初始化上传;上传分块;通知上传
(3)总结
1、Ceph 介绍,官网
Ceph 提供对象、块和文件存储,
2、Ceph 架构,官网
Ceph 集群特点:
- 一个Ceph存储集群至少需要一个Ceph Monitor和两个OSD守护进程。但是,如果要运行Ceph文件系统客户端,那就还需要部署一个元数据服务器Metadata Server.
- Ceph OSDs 负责存储数据,处理数据的的复制、恢复、回填、再均衡,并通过检查其他OSD守护进程的心跳来向Ceph Monitors提供一些监控信息。
- Ceph Monitors 维护者展示集群状态的各种图表
- MDSs 元数据服务器,为Ceph文件系统存储元数据。Ceph块存储和Ceph对象存储不需要MDS。
3、分布式存储
把对象映射给 PG,再把 PG 映射给 OSD
Ceph把客户端的数据保存为存储池内的对象,通过CRUSH算法,Ceph可以计算出哪个PG应该持有的对象,然后进一步计算出哪个OSD守护进程持有该PG。CRUSH算法使得Ceph存储集群可以动态地伸缩、再均衡和修复。
已经通过 Ceph 搭建的私有云存储后,接下来学习阿里云OSS,也就是公有云对象存储服务。
因为开发并且运营一个项目,很多时候团队或者企业都是考虑技术能力、人力成本、时间成本等等因素。
文件存储系统,用户量少的情况下,使用 Ceph 之后,用户上传文件,随便什么存储,但是文件存储规模巨大情况下,就需要增加机器节点拓展集群的规模,或者提高机器配置,另外还要解决高并发带来的各种性能问题,这样运维成本就上去了,考虑这样情况,我们将文件存储到第三方公有云上,这样数据运维部分工作抛给第三方。
1、为什么选择阿里云OSS?
因为阿里云目前的OSS也是比较成熟稳定,用起来也是比较放心。
2、OSS是什么?
OSS 是对象存储服务,适用于存放任意类型文件,以及各种网站。
3、OSS的特点
-
可靠性
-
安全性
-
易使用,官方文档
-
处理能力强,处理海量规模;图片处理;音频视频转码
4、OSS 相关术语
英文 | 中文 |
---|---|
Bucket | 存储空间,桶 |
Object | 对象或文件 |
Endpoint | OSS访问域名 |
ACL | 存储空间或文件权限 |
// |
5、登录管理控制台
6、代码实现
客户端——》上传到服务——》OSS
OSS——》到服务器——》客户端
上面客户端传输到OSS在返回,这个过程耗时有点长,可以使用异步解决这个问题。
上传节点到服务器某个临时节点,然后可以可以立即向客户端返回响应结果,然后文件从上传节点,传输到OSS这个过程是随后某个时间点完成,这过程也是对客户端不可见。
异步逻辑架构:
- 上传流程:文件从客户端传到上传节点的缓冲区,再写到某个指定的目录(临时节点),然后程序往队列扔一条记录,最后返回给客户文件已经存储完毕(但实际是存在临时节点,只是一个异步处理而已)。
- 转移流程:转移流程我们单独或起一组程序监听任务队列,只要队列有记录,那么将队列获取数据进行解析或一定规则读取出来,然后再传到OSS。最后的话临时节点可以删除了
RabbitMQ 工作原理和转发模式:
概述:MQ 是一种遵循 AMQP 协议的 MQ 服务的,它可以解决逻辑耦合,异步任务场景,消息持久化,削峰。
特点:可靠性(持久化、传输确认、发布确认)、可扩展性(可以多个节点)、多语言客户端支持
安装:
docker pull rabbitmq
docker run -d --hostname rabbit-svr --name rabbit -p 5672:5672 -p 15672:15672 -p 25672:25672 -v /mydata/rabbitmq:/var/lib/rabbitmq rabbitmq:nagement
优化:将项目进行微服务化,原来一个系统包含很多模块的(账号管理、文件上传下载、文件转移及数据库管理等等模块)如果其中一个模块出现故障那么整个系统就不可用。所以我将这样一个单体系统打散出来,独立成多个微型服务,然后每个服务都提供比较单一功能,并且也可以单独运行、部署及升级等。
Gin 运行原理:
首先web 程序初始化时候,通过创建engine对象,然后通过这个对象向net.http注册请求对应的handler,在基础之上进行封装路由规则,然后根据http请求方法进行处理用户的请求。
如有问题,欢迎关注我的微信公众号: