0

0

从 Nodejs 到 Go:以单个 Zip 方式增强数千个文件的下载量

PHPz

PHPz

发布时间:2024-08-21 17:54:03

|

789人浏览过

|

来源于dev.to

转载

从 nodejs 到 go:以单个 zip 方式增强数千个文件的下载量

作为开发者,我们在处理大规模数据处理和交付时经常面临挑战。在 kamero,我们最近解决了文件传输管道中的一个重大瓶颈。我们的应用程序允许用户将与特定事件相关的数千个文件下载为单个 zip 文件。此功能由基于 node.js 的 lambda 函数提供支持,负责从 s3 存储桶中获取和压缩文件,但随着我们用户群的增长,该功能一直面临着内存限制和较长执行时间的问题。

这篇文章详细介绍了我们从资源匮乏的 node.js 实现到高效处理大量 s3 下载的精益且快速的 go 解决方案的历程。我们将探索如何优化我们的系统,以便在从特定事件请求大量文件时为用户提供无缝体验,所有文件都打包到一个方便的单个 zip 下载中。

挑战

我们最初的 lambda 函数在处理基于事件的大型文件集时面临几个关键问题:

  1. 内存消耗:即使分配了 10gb 内存,在处理较大事件的 20,000+ 个文件时,该功能也会失败。
  2. 执行时间:具有大量文件的事件的 zip 操作花费的时间太长,有时在完成之前就超时了。
  3. 可扩展性:该功能无法有效地处理不断增加的负载,限制了我们为用户提供流行事件中的大文件集的服务能力。
  4. 用户体验:缓慢的下载准备时间影响了用户满意度,尤其是对于文件数量较多的事件。

node.js 实现:快速浏览

我们最初的实现使用 s3-zip 库从 s3 对象创建 zip 文件。这是我们如何处理文件的简化片段:

const s3zip = require("s3-zip");

// ... other code ...

const body = s3zip.archive(
  { bucket: bucketname },
  eventid,
  files,
  entrydata
);

await uploadzipfile(upload_bucket, zipfilekey, body);

虽然这种方法有效,但它会在创建 zip 之前将所有文件加载到内存中,从而导致大型文件集内存使用率较高,并可能出现内存不足错误。

输入 go:改变游戏规则的重写

我们决定用 go 重写 lambda 函数,利用其效率和内置并发功能。结果令人震惊:

  1. 内存使用量:对于相同的工作负载,从 10gb 降至仅 100mb。
  2. 速度:该功能速度提高了大约 10 倍。
  3. 可靠性:成功处理 20,000 多个文件,没有出现任何问题。

go实现中的关键优化

1. 高效的s3操作

我们使用了 aws sdk for go v2,与 v1 相比,它提供了更好的性能和更低的内存使用量:

cfg, err := config.loaddefaultconfig(context.todo())
s3client = s3.newfromconfig(cfg)

2. 并发处理

go 的 goroutine 允许我们同时处理多个文件:

笔启AI论文
笔启AI论文

专业高质量、低查重,免费论文大纲,在线AI生成原创论文,AI辅助生成论文的神器!

下载
var wg sync.waitgroup
sem := make(chan struct{}, 10) // limit concurrent operations

for _, photo := range photos {
    wg.add(1)
    go func(photo photo) {
        defer wg.done()
        sem <- struct{}{} // acquire semaphore
        defer func() { <-sem }() // release semaphore

        // process photo
    }(photo)
}

wg.wait()

这种方法允许我们同时处理多个文件,同时控制并发级别以防止系统不堪重负。

3. 流式 zip 创建

我们不是将所有文件加载到内存中,而是将 zip 内容直接流式传输到 s3:

pipeReader, pipeWriter := io.Pipe()

go func() {
    zipWriter := zip.NewWriter(pipeWriter)
    // Add files to zip
    zipWriter.Close()
    pipeWriter.Close()
}()

// Upload streaming content to S3
uploader.Upload(ctx, &s3.PutObjectInput{
    Bucket: &destBucket,
    Key:    &zipFileKey,
    Body:   pipeReader,
})

这种流式处理方法显着减少了内存使用量,并允许我们处理更大的文件集。

结果

对 go 的重写带来了令人印象深刻的改进:

  1. 内存使用量:减少 99%(从 10gb 减少到 100mb)
  2. 处理速度:提升约1000%
  3. 可靠性:成功处理 20,000 多个文件,没有出现任何问题
  4. 成本效率:更低的内存使用量和更快的执行时间可以降低 aws lambda 成本

经验教训

  1. 语言选择很重要:go 的效率和并发模型在我们的用例中产生了巨大的差异。
  2. 了解您的瓶颈:分析我们的 node.js 功能帮助我们确定需要改进的关键领域。
  3. 利用云原生解决方案:使用aws sdk for go v2并了解s3的功能可以实现更好的集成和性能。
  4. 以流的方式思考:将数据作为流处理而不是将所有内容加载到内存中对于大规模操作至关重要。

结论

用 go 重写 lambda 函数不仅解决了我们眼前的扩展问题,还为我们的文件处理需求提供了更强大、更高效的解决方案。虽然 node.js 最初为我们提供了良好的服务,但这次经历凸显了为工作选择正确工具的重要性,尤其是在处理大规模资源密集型任务时。

请记住,最好的语言或框架取决于您的具体用例。在我们的场景中,go 的性能特征与我们的需求完美契合,从而显着改善了用户体验并降低了运营成本。

您在无服务器功能方面是否遇到过类似的挑战?你是如何克服它们的?我们很乐意在下面的评论中听到您的经历!

相关专题

更多
lambda表达式
lambda表达式

Lambda表达式是一种匿名函数的简洁表示方式,它可以在需要函数作为参数的地方使用,并提供了一种更简洁、更灵活的编码方式,其语法为“lambda 参数列表: 表达式”,参数列表是函数的参数,可以包含一个或多个参数,用逗号分隔,表达式是函数的执行体,用于定义函数的具体操作。本专题为大家提供lambda表达式相关的文章、下载、课程内容,供大家免费下载体验。

203

2023.09.15

python lambda函数
python lambda函数

本专题整合了python lambda函数用法详解,阅读专题下面的文章了解更多详细内容。

190

2025.11.08

Python lambda详解
Python lambda详解

本专题整合了Python lambda函数相关教程,阅读下面的文章了解更多详细内容。

41

2026.01.05

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

510

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

244

2023.07.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

254

2023.08.03

js是什么意思
js是什么意思

JS是JavaScript的缩写,它是一种广泛应用于网页开发的脚本语言。JavaScript是一种解释性的、基于对象和事件驱动的编程语言,通常用于为网页增加交互性和动态性。它可以在网页上实现复杂的功能和效果,如表单验证、页面元素操作、动画效果、数据交互等。

5267

2023.08.17

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

475

2023.09.01

Java 项目构建与依赖管理(Maven / Gradle)
Java 项目构建与依赖管理(Maven / Gradle)

本专题系统讲解 Java 项目构建与依赖管理的完整体系,重点覆盖 Maven 与 Gradle 的核心概念、项目生命周期、依赖冲突解决、多模块项目管理、构建加速与版本发布规范。通过真实项目结构示例,帮助学习者掌握 从零搭建、维护到发布 Java 工程的标准化流程,提升在实际团队开发中的工程能力与协作效率。

10

2026.01.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
快速入门Node.JS全套完整版
快速入门Node.JS全套完整版

共83课时 | 8.2万人学习

nodejs开发基础教程
nodejs开发基础教程

共15课时 | 4.5万人学习

JavaScript设计模式视频教程
JavaScript设计模式视频教程

共28课时 | 5.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号