開発者として、私たちは大規模なデータの処理と配信を扱うときにしばしば課題に直面します。 Kamiro では最近、ファイル配信パイプラインの重大なボトルネックに取り組みました。私たちのアプリケーションを使用すると、ユーザーは特定のイベントに関連する数千のファイルを単一の zip ファイルとしてダウンロードできます。この機能は、S3 バケットからのファイルのフェッチと圧縮を担当する Node.js ベースの Lambda 関数によって強化されていますが、ユーザーベースが拡大するにつれて、メモリの制約と長い実行時間に悩まされました。
この投稿では、リソースを大量に消費する Node.js 実装から、大規模な S3 ダウンロードを効率的に処理する無駄のない超高速 Go ソリューションへの移行について詳しく説明します。特定のイベントから大量のファイルをリクエストする際に、ユーザーにシームレスなエクスペリエンスを提供するために、システムをどのように最適化し、すべてを 1 つの便利な zip ダウンロードにパッケージ化したかを見ていきます。
私たちの元の Lambda 関数は、大規模なイベントベースのファイルセットを処理する際に、いくつかの重大な問題に直面しました。
私たちの元の実装では、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 を作成する前にすべてのファイルがメモリに読み込まれるため、メモリ使用率が高くなり、大きなファイル セットではメモリ不足エラーが発生する可能性がありました。
私たちは、効率性と組み込みの同時実行機能を活用して、Lambda 関数を Go で書き直すことにしました。結果は驚くべきものでした:
AWS SDK for Go v2 を使用しました。これは、v1 と比較してパフォーマンスが向上し、メモリ使用量が少なくなります。
cfg, err := config.LoadDefaultConfig(context.TODO()) s3Client = s3.NewFromConfig(cfg)
Go のゴルーチンを使用すると、複数のファイルを同時に処理できます。
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()
このアプローチにより、同時実行レベルを制御しながら複数のファイルを同時に処理し、システムに負荷がかかるのを防ぐことができます。
すべてのファイルをメモリにロードする代わりに、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 への書き直しにより、目覚ましい改善がもたらされました。
Go で Lambda 関数を書き直すことで、当面のスケーリングの問題が解決されただけでなく、ファイル処理のニーズに対してより堅牢で効率的なソリューションも提供されました。最初は Node.js が役に立ちましたが、この経験から、特にリソースを大量に消費するタスクを大規模に処理する場合には、ジョブに適したツールを選択することの重要性が浮き彫りになりました。
最適な言語またはフレームワークは、特定の使用例によって異なることに注意してください。私たちのシナリオでは、Go のパフォーマンス特性が私たちのニーズと完全に一致し、その結果、ユーザー エクスペリエンスが大幅に向上し、運用コストが削減されました。
サーバーレス機能に関して同様の課題に直面したことがありますか?どのようにしてそれらを克服しましたか?以下のコメント欄であなたの経験をぜひお聞かせください!
以上がNode.js から Go へ: 数千のファイルのダウンロードを 1 つの ZIP としてスーパーチャージするの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。