这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战
前言
互联网的连接速度慢且不稳定,有可能由于网络故障导致断开连接。
在客户端上传或下载一个大对象时,因网络断开导致上传下载失败的概率就会变得不可忽视。
分块上传和断点续传的适用场景:
-
大文件加速上传
当文件大小超过
5 GB时,使用分片上传可实现并行上传多个Part以加快上传速度。 -
网络环境较差
网络环境较差时,建议使用分片上传。当出现上传失败的时候,您仅需重传失败的Part。
-
流式上传
可以在需要上传的文件大小还不确定的情况下开始上传。这种场景在视频监控等行业应用中比较常见。
为什么需要分块上传:
- 小文件不建议分块上传
- 可以并行上传分块,并且可以无序传输
- 分块上传能极大提高传输效率
- 减少传输失败后重试的流量和时间
对比断点下载,断点上传复杂度有:
- 断点上传的流程则要比断点下载复杂得多, 这是由
HTTP服务的特性导致的。 - 客户端在下载时并不在乎数据的完整性, 一旦发生网络故障, 数据下到哪算哪, 下次继续从最后下载的数据位置开始续传就可以了。
原理
- 初始化上传
- 上传分块(并行)
- 通知上传完成(客户端通知云端)
流程说明如下:
- 将待上传文件按照一定大小进行分片。
- 使用
InitiateMultipartUpload接口初始化一个分片上传任务。 - 使用
UploadPart接口上传分片。 - 文件切分成
Part之后,文件顺序是通过上传过程中指定的partNumber来确定,所以您可以并发上传这些碎片。并发数并非越多越快,请结合自身网络状况和设备负载综合考虑。 - 若您希望终止上传任务,可调用
AbortMultipartUpload接口,成功上传的Part会一并删除。 - 使用
CompleteMultipartUpload接口将Part组合成一个Object。
方案
一般大于
100 MB的文件,建议采用分片上传的方法,通过断点续传和重试,提高上传成功率。
- 对于小对象, 客户端可以使用之前的
PUT方法上传 - 对于大对象, 客户端需要选择
POST方法并自行分块上传
后端需要提供接口:
- 分块上传初始化准备
- 分块上传
- 分块查询
- 分块取消(不需要提供、
HTTP中断即可) - 分块上传结束
上传方案有:
- 服务端签名后直传
- 传统方案
(1)服务端签名后直传
阿里 oss 参考:链接
Tips:无法实现分片上传与断点续传。
服务端签名后直传的原理如下:
- 客户端发送上传
Policy请求到应用服务器 - 应用服务器返回上传
Policy和签名给客户端 - 用户直接上传数据到
OSS
(2)传统方案
实际上,一个后端服务应用会分为计算层和存储层,基本上计算和存储是分离的。
但很多文章都是将这两个概念混合在一起,即一个服务应用既做逻辑计算,又做存储(将文件存储在服务器本地)。
实际分层,如图:
分块上传方式,如图:
- 方式一:存储本地
- 方式二:流式上传
不好理解?可以看下时序图:
基本上后端服务需分布式,能够横向扩展,那么问题来了:
- 合并文件是在服务端,那分布式时如何合并呢?
当然最容易想到是,把对应的请求打到同一个服务上即可啊,如图:
例如,go-fastdfs中集群模式:
http {
// ... ...
proxy_redirect ~/(\w+)/big/upload/(.*) /$1/big/upload/$2; #继点续传一定要设置(注意)
upstream gofastdfs-group1 {
server 10.1.51.70:8082;
server 10.1.14.37:8080;
ip_hash; #notice:very important(注意)
}
upstream gofastdfs-group2 {
server 10.1.51.70:8083;
server 10.1.14.36:8083;
ip_hash; #notice:very important(注意)
}
server {
listen 8000;
server_name localhost;
location /group1 { #以下header要设置
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://gofastdfs-group1;
}
location /group2 {#以下header要设置
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://gofastdfs-group2;
}
}
}
写在最后
估计太干了。没人看吧。拿来参加个活动也好。测试下,哈哈哈。
今天心情好糟糕。
2021.8.6 凌晨了。
为什么心情糟糕呢? 事太多了呗,感觉自己真是老实人,一直干。有的同事是真的恶心人,不去理解产品和需求,天天跑来问。问个问题还没头没尾。