亚马逊AWS官方博客
AWS Lambda 中使用多线程解压 Amazon S3 大文件
当发布网页游戏时,通常会使用 Amazon Simple Storage Service(S3)来存放游戏中的静态资源。这些静态资源数量可达成千上万,如果直接从本地同步这么多文件到 S3,势必会花费较长的时间。
为了优化这个过程,我们可以考虑先将所有静态资源打包成一个 ZIP 文件,然后上传到 S3。ZIP 文件体积较小,上传速度会快很多。上传完成后,我们可以触发 AWS Lambda 服务,自动解压该 ZIP 文件,并将文件上传回指定的 S3。这种方式可以大大缩短发布网页游戏所需的时间。
在传统的 Lambda 自动解压方案中,解压后的上万个文件重新上传回 S3,使用单个线程需要消耗非常长的时间,甚至超过 Lambda 所能运行的最长时间(15 分钟)。您可以在 Lambda 使用多线程的运行,提高大文件解压上传的速度,最大可提高 30 倍,详细可参考文章后面的测试案例。
方案总览
在 S3 收到 zip 文件的上传后,S3 会触发 Lambda 进行下载并解压,解压完成后,通过 Goroutines 多线程的方式将解压后的文件上传到目标 S3 桶中。
部署指南
点击链接 s3-zip-file-uncompress 在 AWS Serverless Application Repository 打开应用页面。输入用于存放解压后文件的 S3 存储桶名称,勾选确定该应用将创建相应的资源策略,点击 Deploy 按钮进行安装。
注意:你可以改变对应的临时存储大小,但需要确保解压后,所有文件所占的空间小于该存储大小。由于 Lambda 目前最大支持的临时存储为 10GB,建议上传的 ZIP 文件不超过 3GB。根据业务需要调整 Lambda 的内存大小及并行执行的线程数量,建议使用默认线程数 100。
安装完成后,你可以在 AWS CloudFormation 的控制台页面中,选择对应的堆栈,并选中 Resources 查看到创建的 Lambda 函数。
点击该 Lambda 函数链接进入到函数详细页面,通过点击 Add trigger 按钮增加触发器。
在 Trigger configuration 页面中,选择 S3 为触发源并选择对应的用于上传 zip 文件的存储桶。Event types 中,选择 All object create events 并在 Suffix 中设置只有后缀为 .zip 的文件会触发事件,勾选须知并点击 Add 按钮进行添加。
在设置触发配置完成以后,当往 S3 存储桶上传 zip 文件的时候,将会自动触发 Lambda 对该 zip 文件进行解压并上传到指定的 S3 中。
(可选)增加 Lambda 执行结果的主动通知。在 Lambda 函数页面中点击 Add destination 增加成功或失败时的消息推送。
测试解压速度
上传大 zip 包进行测试,该 zip 包大小为 500M 并包含 1.3 万个小文件,Lambda 在分配 3G 内存时不同线程数设置下的执行时间对比。
在线程数设置越高的情况下,Lambda 所执行的时间越短。同时,由于 Lambda 文件描述符的限制,在线程数超过 100 的情况下继续提高并不能获得更多的收益。
清理环境
为避免产生不必要的费用,在 CloudFormation 的 Stacks 中,选择对应的堆栈进行并点击 Delete。
总结
在这篇文章中,您通过在 Serverless Application Repository 中安装应用,实现了对上传到 S3 中的大文件进行自动解压并上传到目标 S3 存储桶中的功能。在接收到 S3 的上传文件事件时将触发 Lambda 函数,它会启动多线程来加速解压和上传。通过 Lambda 的多线程处理,在大幅执行速度的同时也降低了 Lambda 的使用费用。