二方土君

如何让上传速度加快10倍——草案博客

二方土君 · 2017-02-12翻译 · 366阅读 原文链接

你觉得你的web应用只可以响应得更快一点吗?我们觉得可以所以做了一点新的尝试

“高层次的抽象” 作者: Tomasz Urbaszek

我们会对在发现应用响应慢的时候做一些优化,但是现实效果都不怎么满意。正如它所显示的,最慢的部分是在我们应用中上传文件的时候。然而是否还有加快上传文件速度的可能呢?

在我们着手优化之前先来一个简短的介绍。如果你是正在处于一个商业应用的开发当中,你有可能会遇到关于应用不能及时响应的需求。问题的瓶颈可能是由以下的其中一点造成的:

  • 极少的优化代码

  • 服务器或客户设备运行慢

  • 不好的网络条件

第一条,无论是遗留下来的代码,没有优化的数据库查询语句或者在浏览器的JavaScript代码块,都可以相对轻松地跟踪和修复。(轻松的意思是指“我知道这该怎么做”,而不必是“这是小菜一蹀”)。

假设你的代码已经很高质量了,但是你的服务器还是无法很好地对所有用户提供服务的时候——这实际上听起来像是一个对你和你的业务相当好的一个信号。你可能会通过更换更强大的服务器来处理所有正在增长的请求。还是说它可能只是一个高度隐藏的潜在问题?那么网络分发内容 (CDN)这篇文章可以是你需要的。

web应用一般不会因为用户设备而运行慢,因为几乎所有设备都可以运行能够提供相当好体验的浏览器。

所有关于因特网的文章似乎都有一张照着路由器和网缆的图片 ¯(ツ)

我们现在只剩下个可能的原因了:差的网络条件。虽然现在的网络下载的速度越来越快,但是你还是主动地通过资源最小化和压缩等方法来要让你的网店加载得更快。所有的现代网站服务器都支持gzipped文件压缩技术,这是一种能让客户端下载最少数据来显示你 的网站的技术。(如果你还没有使用gzip来压缩,这也许是个好机会来考虑一下这样做)。但是如果你想通过其它方式来加快响应,那又该怎么做呢?

欢迎来到上传的未知领域

上传文件这个过程有什么东西是还非常不了解的呢?对于初学者来说,如果我们对比一下上传和下载的速度,会发现很多人用的是不对称的因特网(尽管你不是网络的源头,但你也是这网络中的其中一员不是吗?)。因此不对称网络就意味着上传速度会比下载速度慢10倍以上。所以当用着60Mbps的网络时感觉速度还不错,但6Mbps的上传听起来就相当的慢了。这实际上还不到1MB/s。

这感觉就像8Mbps的网络来上传一个160MB大小的文件那样令人沮丧不是吗? ლ(ಠ_ಠლ)

此外,不像服务器,浏览器没有自带在上传之前压缩数据的能力。所以有了在慢网络下上传大文件会卡死的情况发生了。

我们提出一个解决这个问题的简单主意。在我们不用强迫人们更换更快网络的情况下,我们可以参考在服务器那样的解决方案,尝试发送更少的数据。但是怎么才能在浏览器上传之前压缩一下数据呢?

初见Pako

什么是pako?根据介绍,它是一个_zlib的javascript接口,非常的快!换句话说,我们使用pako就能给浏览器加上了强大的gizp数据压缩功能,刚好符合我们之前讨论的解决方案,而且还省力省心。举个例子,在我们上传文件之前,你可以通过这行命令来压缩数据:

**var** compressed_file = pako.deflate(input_file);

这不是很简单吗?不过先让我们停下来讨论一下什么时候你才真正地需要压缩数据。

我们不能把所有的东西都拿去压缩

首先,你是可以把所有的数据都拿去压缩的,但是这并不很符合常规。比如,你不需要使用gzip对图片或者视频进行压缩(至少大多数它们标准的格式像jpg或者mpeg已经经过很大程度的压缩了)。

在另一方面,对于文本数据,已经压缩得很好了。而对于文件,我们一直期待能够达到90%的压缩比率,而且纯文本还要被打包得很好。在我们案例中就是关于3D的文件(obj, stl 等等)。对于你来说也许是一些Excel的文件或者Photoshop的大文件等着上传。不管,反正要先试图把它们压缩,之后你就会对压缩后省下的空间而感到惊讶。

第一行是没有被压缩过的文件,第二行是经过压缩后的同一份文件

但是压缩的过程是很慢的

然后接下来就是上传文件了。还记得我们是怎么讨论异步网络的?在上传速度很慢的情况下,关键的地方就是应该考虑怎么让压缩时间比上传的时间少。想要实现这一点其实并不困难,只要你的文件已经经过了很好的压缩。上传压缩过的小文件会比上传未压缩的大文件快。

为了确保我们在压缩的时候不会花太多的时间,我们会用最低的压缩档次(9分之1),这是一个最快地显著减少文件大小的模式。在大多数情况下你不会使用更高的压缩档次。

就像你所看到的那样,为了提高2-3%的压缩比率,我们需要花费更多更多的压缩时间。(在这个点上我应该向你展示一个关于时间和文件大小的对比图表,但是后来我觉得也许让你自己去实践获得的对比效果会更好)

你只需要传一个level选项就可以改变pako的压缩档次,就像下面语句:

**var** compressed_file = pako.deflate(input_file, {level: 1});

现在既然我们知道了一系列的可以加快上传的解决方法,就让我们来检查一下应用它们的实际效果。

我们真的使上传变得更快了吗?

事实上是的。

左边的是上传未经压缩的文件,而右边的则是经过压缩过的。我们很容易在它们俩中作出选择。

在经过针对这个方法一段时间的测试后,我们决定把它使用到我们的app项目中。在我们项目中,我们要上传一些JSON格式的3D模型数据。在压缩之前,他们有时会达到5-6MB。而这些文件的压缩比率可以达到90%,也就是说我们只要上传0.6M的数据来代替6MB。现在,在6Mbps的上传速度环境下,客户只要等待0.8s而不是8s就可以上传完毕。期间压缩这些文件也只是花了少于0.1s的时间,所以我们决定采用这种方案。

但是你不必一定相信我。在最后我从网上随机地抽取一些人。

为什么你不去实践一下

我准备了一个很小的demo应用 来让你决定是否能在你的项目中使用。在选择上传速度和选择需要上传的文件后,这个demo应用会自动地压缩它和模拟上传过程。你不用担心它是否真的上传你所选择的文件并随便发布到其它地方,它只是单纯地改变进度条,以便你可以对上传这些未压缩和压缩过的文件所需的时间进行对比。

在你的应用是尝试上传一些文本文件、二进制数据或者其它你想上传的东西。

接下来是什么?

还有一些事我们需要记得。最重要的就是现在你的服务接收的是经过压缩的数据,因此你必需要去解压后才能使用它。解压是永远比压缩快的,所以不必担心我们会在解压上花费很多额外的时间。

另外一个需要留意的是压缩不是瞬间就完成的。对于一个很大的文件可能会需要一些时间来上传(比如一些大小为450MB的文件,你可能需要等等大约30秒的时间来上传)。为了良好的用户体验,应该尽量地让你的网站不处于阻塞状态,可能用分块来上传文件(pako已经支持这个功能),或者尝试一些Web Workers

好了,就是这么的简单,不知道在你看完这个解决方案后对你的应用会有什么帮助呢?

译者二方土君尚未开通打赏功能

相关文章