”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 从 Node.js 到 Go:以单个 Zip 方式增强数千个文件的下载量

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

发布于2024-08-24
浏览:484

From Node.js to Go: Supercharging Sownloads of Thousands of Files as a Single 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 允许我们同时处理多个文件:

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 



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

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 的性能特征与我们的需求完美契合,从而显着改善了用户体验并降低了运营成本。

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

版本声明 本文转载于:https://dev.to/hiteshsisara/from-nodejs-to-go-supercharging-s3-downloads-of-thousands-of-files-as-a-single-zip-474b?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • WebRTC简介
    WebRTC简介
    安装和代码指南 WebRTC(网络实时通信)是一种开源技术,可通过网络浏览器和移动应用程序中的简单 API 实现实时通信。它允许在点之间直接共享音频、视频和数据,无需中间服务器,非常适合视频会议、直播和文件共享等应用。 在本博客中,我们将深入探讨以下主题: 什么是WebRTC? W...
    编程 发布于2024-11-06
  • 如何在不使用 JavaScript 的情况下使用 CSS 隐藏和显示内容?
    如何在不使用 JavaScript 的情况下使用 CSS 隐藏和显示内容?
    使用 CSS 隐藏和显示内容:无需 JavaScript 的技巧在进行 Web 开发时,控制内容的可见性通常至关重要。传统上,这是使用 JavaScript 实现的,但 CSS 也可用于创建优雅的隐藏和显示效果。下面描述了一种此类技术,解决了先前方法遇到的特定挑战。隐藏/显示内容切换:可以使用 CS...
    编程 发布于2024-11-06
  • 如何创建重复最少的 5 个字符的随机字符串?
    如何创建重复最少的 5 个字符的随机字符串?
    生成 5 个具有最少重复的随机字符要创建具有最少重复的随机 5 个字符字符串,最有效的方法之一是使用PHP 函数和巧妙技术的结合。让我们深入研究解决方案:使用 md5 和 rand$rand = substr(md5(microtime()),rand(0,26),5);该方法使用md5哈希函数根据...
    编程 发布于2024-11-06
  • 如何在 Go 中处理不同包之间相同的方法签名?
    如何在 Go 中处理不同包之间相同的方法签名?
    处理不同包中具有相同方法签名的接口在Go中,当处理具有相同方法签名但定义在不同包中的多个接口时,可能会出现以下情况实现两个接口的类型会导致意外行为。考虑在不同包中定义的这两个接口(Doer)和函数(FuncA 和 FuncB):// Package A type Doer interface { D...
    编程 发布于2024-11-06
  • 如何使用 jQuery 填充级联下拉列表以获得更好的兼容性和用户体验?
    如何使用 jQuery 填充级联下拉列表以获得更好的兼容性和用户体验?
    使用 jQuery 填充级联下拉列表在表单开发领域,级联下拉列表经常用于提供更加用户友好和动态体验。为了增强兼容性并解决跨浏览器问题,jQuery 提供了一个强大的解决方案来异步填充这些下拉列表。问题中所示的用于创建级联下拉列表的原始 JavaScript 函数缺乏与 IE 的兼容性。为了解决这个问...
    编程 发布于2024-11-06
  • 了解 JavaScript 中的扩展运算符:初学者简单指南
    了解 JavaScript 中的扩展运算符:初学者简单指南
    介绍 JavaScript 是一种有趣的编程语言,其最令人兴奋的功能之一是扩展运算符。如果您刚刚开始编码,或者即使您是一个对学习 JavaScript 感兴趣的孩子,也不必担心!我将以最简单的方式分解这个概念,并举例来帮助您理解。 什么是价差运算符? 扩展运算符看起...
    编程 发布于2024-11-06
  • 在 Python 中使用 OpenSearch 掌握 CRUD 操作:实用指南
    在 Python 中使用 OpenSearch 掌握 CRUD 操作:实用指南
    OpenSearch, an open-source alternative to Elasticsearch, is a powerful search and analytics engine built to handle large datasets with ease. In this b...
    编程 发布于2024-11-06
  • 冰沙框架的重要概念||如何精通冰沙
    冰沙框架的重要概念||如何精通冰沙
    要精通 Frappe,有几个关键概念和领域需要关注。以下是最重要的细分: 1. 文档类型 定义:DocTypes是Frappe中的核心数据模型。每个实体或记录都存储在 DocType 中,并且它们可以具有字段、权限和工作流程。 为什么它很重要:了解如何创建和自定义 DocType 至...
    编程 发布于2024-11-06
  • 如何解决 JLabel 拖放的鼠标事件冲突?
    如何解决 JLabel 拖放的鼠标事件冲突?
    用于拖放的 JLabel 鼠标事件:解决鼠标事件冲突为了在 JLabel 上启用拖放功能,鼠标事件必须被覆盖。然而,当尝试使用 mousePressed 事件实现拖放时,会出现一个常见问题,因为 mouseReleased 事件对该 JLabel 无效。提供的代码在 mousePressed 事件中...
    编程 发布于2024-11-06
  • MySQL 中的数据库分片:综合指南
    MySQL 中的数据库分片:综合指南
    随着数据库变得越来越大、越来越复杂,有效地控制性能和扩展就出现了。数据库分片是用于克服这些障碍的一种方法。称为“分片”的数据库分区将大型数据库划分为更小、更易于管理的段(称为“分片”)。通过将每个分片分布在多个服务器上(每个服务器保存总数据的一小部分),可以提高可扩展性和吞吐量。 在本文中,我们将探...
    编程 发布于2024-11-06
  • 如何将 Python 日期时间对象转换为秒?
    如何将 Python 日期时间对象转换为秒?
    在 Python 中将日期时间对象转换为秒在 Python 中使用日期时间对象时,通常需要将它们转换为秒以适应各种情况分析目的。但是,toordinal() 方法可能无法提供所需的输出,因为它仅区分具有不同日期的日期。要准确地将日期时间对象转换为秒,特别是对于 1970 年 1 月 1 日的特定日期...
    编程 发布于2024-11-06
  • 如何使用 Laravel Eloquent 的 firstOrNew() 方法有效优化 CRUD 操作?
    如何使用 Laravel Eloquent 的 firstOrNew() 方法有效优化 CRUD 操作?
    使用 Laravel Eloquent 优化 CRUD 操作在 Laravel 中使用数据库时,插入或更新记录是很常见的。为了实现这一点,开发人员经常求助于条件语句,在决定执行插入或更新之前检查记录是否存在。firstOrNew() 方法幸运的是, Eloquent 通过firstOrNew() 方...
    编程 发布于2024-11-06
  • 为什么在 PHP 中重写方法参数违反了严格的标准?
    为什么在 PHP 中重写方法参数违反了严格的标准?
    在 PHP 中重写方法参数:违反严格标准在面向对象编程中,里氏替换原则 (LSP) 规定:子类型的对象可以替换其父对象,而不改变程序的行为。然而,在 PHP 中,用不同的参数签名覆盖方法被认为是违反严格标准的。为什么这是违规?PHP 是弱类型语言,这意味着编译器无法在编译时确定变量的确切类型。这意味...
    编程 发布于2024-11-06
  • 哪个 PHP 库提供卓越的 SQL 注入防护:PDO 还是 mysql_real_escape_string?
    哪个 PHP 库提供卓越的 SQL 注入防护:PDO 还是 mysql_real_escape_string?
    PDO vs. mysql_real_escape_string:综合指南查询转义对于防止 SQL 注入至关重要。虽然 mysql_real_escape_string 提供了转义查询的基本方法,但 PDO 成为了一种具有众多优点的卓越解决方案。什么是 PDO?PHP 数据对象 (PDO) 是一个数...
    编程 发布于2024-11-06

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3