博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
开发函数计算的正确姿势——使用 brotli 压缩大文件
阅读量:6903 次
发布时间:2019-06-27

本文共 4553 字,大约阅读时间需要 15 分钟。

hot3.png

大文件问题

函数计算对上传的 zip 代码包尺寸限制为 50M。某些场景中代码包中会超过这一限制,比如二进制  经过一番裁剪以后 ZIP 压缩包的体积为 43.4M,类似的还有 liboffice ,此外常见的还有机器学习训练的模型文件。

目前解决大文件问题有三种方法

  1. 采用更高压缩比的算法,比如本文介绍的 brotli 算法
  2. 采用 OSS 运行时下载
  3. 采用 NAS 文件共享

简单的比较一下这三种方法的优劣

方法 优点 缺点
高密度压缩 发布简单,启动最快 上传代码包较慢;要写解压代码;大小受限制不超过 50 M
OSS 下载解压后文件不超过 512 M 需要预先上传至 OSS;要写下载和解压代码,大概 50M/s 的下载速度
NAS 文件大小没有限制,无需压缩 需要预先上传至 NAS;VPC 环境有冷启动时延(~5s)

正常情况下如果代码包能控制在 50M 以下启动较快。而且工程上也比较简单,数据和代码放在一起,不需要额外的写脚本去同步更新 OSS 或者 NAS。

压缩算法

 是 Google 工程师开发的开源压缩算法,目前已经被新版的主流浏览器支持,作为 HTTP 传输的压缩算法。下面是在网上找到的关于 Brotli 和其他常见压缩算法对比基准测试。

从上面三幅图我们可以看出:相比于 gzip、xz 和 bz2,brotli 有最高的压缩比,接近于 gzip 的解压速度,以及最慢的压缩速度。

然而在我们的场景对于压缩慢这一缺点不敏感,压缩任务只要在开发准备物料的阶段执行一次就好了。

制作压缩文件

下面我先介绍一下如何制作压缩文件。下面的代码和用例都来自于项目  。

安装 brotli 命令

Mac 用户

brew install brotli

Windows 用户可以去这个界面下载,

打包并压缩

打包前两个文件大小分别为 7.5M 和 97M

╭─ ~/D/test1[◷ 18:15:21]╰─  lltotal 213840-rwxr-xr-x  1 vangie  staff   7.5M  3  5 11:13 chromedriver-rwxr-xr-x  1 vangie  staff    97M  1 25  2018 headless-chromium

使用 GZip 打包并压缩,大小为 44 M。

╭─ ~/D/test1[◷ 18:15:33]╰─  tar -czvf chromedriver.tar chromedriver headless-chromiuma chromedrivera headless-chromium╭─ ~/D/test1[◷ 18:16:41]╰─  lltotal 306216-rwxr-xr-x  1 vangie  staff   7.5M  3  5 11:13 chromedriver-rw-r--r--  1 vangie  staff    44M  3  6 18:16 chromedriver.tar-rwxr-xr-x  1 vangie  staff    97M  1 25  2018 headless-chromium

tar 去掉 z 选项再打包一遍,大小为 104M

╭─ ~/D/test1[◷ 18:16:42]╰─  tar -cvf chromedriver.tar chromedriver headless-chromiuma chromedrivera headless-chromium╭─ ~/D/test1[◷ 18:17:06]╰─  lltotal 443232-rwxr-xr-x  1 vangie  staff   7.5M  3  5 11:13 chromedriver-rw-r--r--  1 vangie  staff   104M  3  6 18:17 chromedriver.tar-rwxr-xr-x  1 vangie  staff    97M  1 25  2018 headless-chromium

压缩后的大小为 33M,相比 Gzip 的 44M 小了不少。耗时也非常的感人 6 分 18 秒,Gzip 只要 5 秒。

╭─ ~/D/test1[◷ 18:17:08]╰─  time brotli -q 11 -j -f chromedriver.tarbrotli -q 11 -j -f chromedriver.tar  375.39s user 1.66s system 99% cpu 6:18.21 total╭─ ~/D/test1[◷ 18:24:23]╰─  lltotal 281552-rwxr-xr-x  1 vangie  staff   7.5M  3  5 11:13 chromedriver-rw-r--r--  1 vangie  staff    33M  3  6 18:17 chromedriver.tar.br-rwxr-xr-x  1 vangie  staff    97M  1 25  2018 headless-chromium

运行时解压缩

下面以 java maven 项目为例

添加解压依赖包

org.apache.commons
commons-compress
1.18
org.brotli
dec
0.1.2

commons-compress 是 apache 提供的解压缩工具包,对于各种压缩算法提供一致的抽象接口,其中对于 brotli 算法只支持解压,这里足够了。org.brotli:dec 包是 Google 提供的 brotli 解压算法的底层实现。

实现 initialize 方法

public class ChromeDemo implements  FunctionInitializer {    public void initialize(Context context) throws IOException {        Instant start = Instant.now();        try (TarArchiveInputStream in =                     new TarArchiveInputStream(                             new BrotliCompressorInputStream(                                     new BufferedInputStream(                                             new FileInputStream("chromedriver.tar.br"))))) {            TarArchiveEntry entry;            while ((entry = in.getNextTarEntry()) != null) {                if (entry.isDirectory()) {                    continue;                }                File file = new File("/tmp/bin", entry.getName());                File parent = file.getParentFile();                if (!parent.exists()) {                    parent.mkdirs();                }                System.out.println("extract file to " + file.getAbsolutePath());                try (FileOutputStream out = new FileOutputStream(file)) {                    IOUtils.copy(in, out);                }                Files.setPosixFilePermissions(file.getCanonicalFile().toPath(),                        getPosixFilePermission(entry.getMode()));            }        }        Instant finish = Instant.now();        long timeElapsed = Duration.between(start, finish).toMillis();        System.out.println("Extract binary elapsed: " + timeElapsed + "ms");    }}

实现 FunctionInitializer 接口的 initialize 方法。解压过程刚开始是四层嵌套流,作用分别如下:

  1. FileInputStream 读取文件
  2. BufferedInputStream 提供缓存,介绍系统调用带来的上下文切换,提示读取的速度
  3. BrotliCompressorInputStream 对字节流进行解码
  4. TarArchiveInputStream 把 tar 包里的文件逐个解出来

然后 Files.setPosixFilePermissions 的作用是还原 tar 包中文件的权限。代码太长此处略去,参阅 

Instant start = Instant.now();...Instant finish = Instant.now();long timeElapsed = Duration.between(start, finish).toMillis();System.out.println("Extract binary elapsed: " + timeElapsed + "ms");

上面的代码段会打印出解压的耗时,真实执行大概在 3.7 s 左右。

最后不要忘记在 template.yml 里配置上 Initializer 和 InitializationTimeout

参考阅读

转载于:https://my.oschina.net/u/1464083/blog/3019688

你可能感兴趣的文章
CentOS7切换图形启动模式
查看>>
利用python分析日志生成图表
查看>>
c#中不定长参数(关键字Params)使用
查看>>
WinAPI: waveOutPause - 暂停播放
查看>>
FTP自动上传
查看>>
我的友情链接
查看>>
mysqldump工具
查看>>
用 PHP 读取文件的正确方法
查看>>
LoadRunner压力测试时监控服务器Linux的资源情况
查看>>
azure存储并发写 压力测试
查看>>
管理用户和用户权限
查看>>
VCTransitionsLibrary –自定义iOS交互式转场动画的库
查看>>
final、static(Java)和const、static(C#)
查看>>
C语言利用中心极限定理产生高斯白噪声
查看>>
电脑定时关机
查看>>
Disconf-Web管理端安装
查看>>
PHP-防止SQL注入
查看>>
Javascript监听 ESC按下事件
查看>>
Comet技术详解:基于HTTP长连接的Web端实时通信技术
查看>>
MongoDB:Ruby中嵌入Javascript实战
查看>>