文档章节

服务器端文件分片合并的思考和实践

 天下杰论
发布于 2016/04/13 10:07
字数 1625
阅读 71
收藏 2

大文件的需求

文件上传是个很常见的需求。尽管HTTP是基于TCP上层的协议,但是HTTP协议本身并不适合处理超大的请求体,文件上传有很大的稳定性问题,如果中途断开了,将前功尽弃。为了改善用户体验或者缓解服务器压力,通常会考虑将文件分成小片,将小片一个个上传,如果中途断开了也能从某个失败的小片开始继续上传。

在前端的处理上,对于Web页面,可以采用plupload作为上传组件,该组件支持html5、flash、sl等多种上传方式,因此,可以提供较好的浏览器兼容性。

服务器端的策略

既然文件被分成片上传,那么自然在服务器端需要将分片合并成原始的文件,那么这里存在两种策略

边传边合并:每上传一个分片,就将分片合并到文件的后面

传完一起合并:先将分片保存起来,客户端发起一个合并请求时,再将分片合并成一个文件

边传边合并

这种方式要注意:

由于HTTP的无状态性,这种方式需要客户端和服务器端维持一个标识。服务器端根据标识,才能知道分片应该向哪个目标文件Append

如果客户端中途停止上传,那么保存在服务器上的目标文件将成为垃圾文件,文件即不能被删除又没有利用价值。因为服务端无法知道文件究竟的完成状态还是正在进行状态

由于分片直接合并进了文件,无法管理分片

传完一起合并

具体的实现方式如下:

1、每上传一个分片,服务端将分片保存下来,并返回客户端一个唯一标识ctx,这个标识ctx与当前这个分片关联

2、客户端应当妥善保存每个分片的标识,以及它们的先后顺序

3、服务端需要提供一个接口,客户端用这个接口请求分片合并,在请求时候将标识按顺序告知服务端,ctx0,ctx1,ctx2...

4、服务端根据标识的顺序找到对应的分片,并合并成完成的文件

这种设计解决了客户端中途停止上传带来的服务器端资源的浪费,因为分片都是正在进行态,可以对时间很早的分片进行清理。而且分片被记录了下来,容易对分片进行一些管理。

服务器端的分片合并

现在进入本文的重点。文件合并是IO操作,IO操作是最耗时的工作了。上文的第一种策略,有一个好处是文件的合并是在上传的过程中完成的,对于用户来说几乎感知不到文件Append时的延时。然而,第二种策略的文件合并却是在一个时刻同时进行的。笔者测试过,即使是4-5个4MB的分片,也会使客户端有明显的延迟感。如果分片再多的话,延迟将更大,甚至请求超时,这是不能接受的。

并行处理?

由于是将分片合并,那么很容易会想到并行。类似归并排序的思想,将合并任务分开,然后通过集群服务器的协调完成合并。但是笔者对这方面是知之甚少,而且这种方案会使原本简单的架构变的异常复杂,不敢采用这种方案。而且感觉会有坑:

并行处理往往是异步的,如何处理好与web服务器的同步

再怎么分任务,合并终究是IO操作,IO操作总是要耗费时间的

文件系统底层处理?

仔细思考合并这个动作,实际上是将多个文件在文件系统里面复制了一次,而文件的内容并没有任何的变化。如果能够在文件系统层面将分片直接连接起来话,合并文件仅仅是修改一些指针,速度将十分的快。不过文件系统各不相同,能不能实现还需要看。而且,由于笔者使用nfs作为数据存储,nfs的文件读写完全是通过接口提供的,接口也不提供底层的文件系统操作,所以似乎是无法实现。

为什么非要合并!

再思考下去,如果文件系统无法做到将分片直接连接起来的的话,那么从用户接口层(HTTP)是否能做到呢?试想,通过HTTP的方式提供文件的访问,如果HTTP服务器能够知道这个文件是由多个小文件按何种顺序组成的,那么就可以按照顺序将分片依次放在同一个HTTP流中返回,对用户来说一次请求还是得到一个文件,好像文件是合并好的一样,但实际上文件在文件系统并不存在。

这样做需要单独将分片的顺序维护好,每次都要读出分片的顺序和位置,然后依次一个个写入HTTP流中。但是高层的Web编程框架似乎无法支持这种做法。

巧用Nginx避免文件合并

笔者立刻想到了之前用过的Nginx模块mod_zip,这个模块能够将多个文件打包以zip流的方式返回。现在的需求其实跟这个模块的工作几乎差不多,甚至还要更简单。

后续还是要合并的

现在用户那头可以"欺骗"成功了,但是如果系统本身需要对文件进一步处理,比如视频的格式转换,那么还是需要将文件合并起来的,不过这个时候就可以用一个后台的服务异步的慢慢做了,用户不会感知。基于这些复杂的问题,笔者已经把文件上传下载和处理作为的一个全新的产品功能独立出来,以支持主产品对文件的各种功能需求。

 

本文转载自:https://segmentfault.com/a/1190000000725971

共有 人打赏支持
粉丝 54
博文 443
码字总数 23611
作品 0
沈阳
项目经理
私信 提问

暂无文章

多表查询

第1章 多表关系实战 1.1 实战1:省和市  方案1:多张表,一对多  方案2:一张表,自关联一对多 1.2 实战2:用户和角色 (比如演员和扮演人物)  多对多关系 1.3 实战3:角色和权限 (比如...

stars永恒
今天
6
0
求推广,德邦快递坑人!!!!

完全没想好怎么来吐槽自己这次苦逼的德邦物流过程了,只好来记一个流水账。 从寄快递开始: 2019年1月15日从 德邦物流 微信小app上下单,截图如下: 可笑的是什么,我预约的是17号上门收件,...

o0无忧亦无怖
昨天
6
0
Mac Vim配置

1.升级 vim   我自己 MacBook Pro 的系统还是 10.11 ,其自带的 vim 版本为 7.3 ,我们将其升至最新版: 使用 homebrew : brew install vim --with-lua --with-override-system-vim 这将下...

Pasenger
昨天
8
0
vmware安装Ubuntu上不了网?上网了安装不了net-tools,无法执行ifconfig?

1.重新设置网络适配器还是不行,如下指定nat 2.还需要指定共享网络,我是在无线环境下 3.无法执行ifconfig https://packages.ubuntu.com/bionic/net-tools到这个网站下载net-tools的deb文件...

noob_chr
昨天
4
0
解决SVN:E210007无法协商认证机制

svn:E210007 svn: Cannot negotiate authentication mechanism 执行下面代码即可 sudo yum install cyrus-sasl cyrus-sasl-plain cyrus-sasl-ldap...

临江仙卜算子
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部