简介
本文根据作者的实践及材料汇总,讨论移动网络下文件上传涉及到的几个问题。对于一些问题,不谈解决方案,只谈利弊。
-
移动网络(相对有线网络)的一些特点
腾讯原创分享(一):如何大幅提升移动网络下手机QQ的图片传输速度和成功率要点:
- 网络好时提高速度率;网络差时提高成功率
- 移动网络容易出现“跳变”,下一秒中的传送速度可能降到前一秒的几十分之一,RTO(超时重传机制)容易因为超时导致大量失败
- 移动网络里经常会有“网络真空 (NV)”,即便信号满格也传不出去 1 个字节。
-
移动网络上传场景
- 音频、短视频、视频
- IM语音、图片等
笔者曾经实现的一个简单方案
上传文件的基本过程:
- create请求,向server报告要上传文件。server若同意,返回一个文件标识,id或name
- 发送文件数据
音频上传,采用netty实现:
上传流程如下:
缺点:
- 转发host(图中的forwarder) 不够高效
-
executor(实际负责文件处理)中存在阻塞逻辑
- netty中直接调用fdfs上传文件,原因:要向客户端返回文件id
- 数据采集、统计和查询能力几乎没有
当时的一些考虑:
- 使用tcp的理由:http容易被运营商劫持
- 有一个专门的转发host:对外端口有限;单个文件的完整处理过程耗时稍长,转发器只负责转发,文件的处理能力通过加executor机器扩展。
- 断点续传:简化客户端开发
要理清的几个问题
-
是否采用分片,分片是自定义协议,还是http chunk。如何让你产品的用户拥有一流的上传体验网易云采用自定义的http方式
- 4g和wifi网络下,分片大小不同
- 是否保留转发
-
接收端避免随机读写数据数据。
- 接收端将接收到的数据,写入内存即返回,由类似kafka的accumulator将内存中的数据整理落盘,或者由内存直接上传fastfs
- 根据接收文件块的顺序 顺序写入文件,同时记录文件块与实际文件中的位置的关系,在上传文件时,重新恢复成原文件
-
整个上传过程中,http与tcp的关系。
- 全用http协议
- 全用tcp协议
- http与tcp协议混合。哪些信息通过http方式完成,哪些信息通过tcp方式完成?
- 接收端如何与存储系统对接,接收端将文件落盘到本地后,还需要将文件上传到dfs中。
-
接收端如何与业务系统对接,server应该在文件数据接收完毕后,返回client一个file id,以便client可以根据file id 获取文件对应的business id。
- 文件上传系统调用业务系统完成声音、视频的转码、图片的裁剪等,一些就绪后,返回文件的business id
- 文件上传系统只负责将文件上传到文件存储系统中,然后发消息通知业务系统
- 上传系统的目标:公司各个场景的统一的上传平台。包括录音,群聊的图片、语音,私信的语音,富音频等
协议
- 基于tcp定制协议
- 基于http定制协议 tus/tus-resumable-upload-protocol,从中可以学到一下几点:
一个协议包括,请求、响应。请求包括查询信息、上传文件、重传文件、查询文件断点等。协议的制定通常有两种风格:
-
一个结构包办所有情况,比如
length,8 byte request or response, 1 byte type, 4 byte param length, 4 byte params, param length byte body length, 4 byte body , body length byte
这样做的缺点就是
- 所有请求类型的编解码在一个编码器里面
- 请求的分发略微复杂
- 新增一个请求类型,要更改当前的编解码器以及请求处理流程
-
每一种交互定义一个结构
此外,一个交互的包大小不应过大。否则,一个包无法在内存中完成编解码,或者server无法做到多个包同时在内存中进行编解码,也就无法支撑较大的并发量。即或server可以边解码边消费,不用缓存在内存,内存也需要维护包数据的上下文信息,增加了不可靠性。
分片
在移动网络下,分片上传文件几乎是毫无疑问的。
分片协议
假设只有两个分片
-
分片连续发送
- 发送create请求,表示要上传文件,并采用分片,表明文件大小
- 上传分片1
- 上传分片2
服务端自行判断文件是否接受完整,合并分片并处理
-
将分片当成文件发送
- 发送create请求,上传分片1
- 发送分片1数据
- 发送create请求,上传分片2
- 发送分片2数据
- 发送create请求,表示要上传原文件
- 发送数据,数据内容为分片的归并信息
服务端对分片的处理
-
对接收到的分片立即持久化,缺点:持久化工作较为耗时,影响服务端性能
-
同一个分片存储在同一个文件中,缺点:并发访问文件
- 预先分配好文件空间,按文件位置持久化
- 按分片接收顺序持久化,同时存储分片与位置的映射关系
-
单纯的将分片持久化,一个分片存储为一个文件
-
-
将接收到的分片缓存到内存中,等文件接收完毕后持久化,缺点:没那么大内存
现有的开源云存储系统
这里指带有完善的后端 + 前端套件
-
tus,后端采用Go语言,基于http协议上传文件。
-
haiwen/seafile 后端采用C+Python,文件上传协议http
-
ownCloud 及其衍生的nextcloud,后端采用php