„Wenn ein Arbeiter seine Arbeit gut machen will, muss er zuerst seine Werkzeuge schärfen.“ – Konfuzius, „Die Gespräche des Konfuzius. Lu Linggong“
Titelseite > Programmierung > Von Node.js bis hin zu Go: Laden Sie Tausende von Dateien in einer einzigen Zip-Datei auf

Von Node.js bis hin zu Go: Laden Sie Tausende von Dateien in einer einzigen Zip-Datei auf

Veröffentlicht am 24.08.2024
Durchsuche:523

From Node.js to Go: Supercharging Sownloads of Thousands of Files as a Single Zip

Als Entwickler stehen wir oft vor Herausforderungen, wenn es um die Verarbeitung und Bereitstellung umfangreicher Daten geht. Bei Kamero haben wir kürzlich einen erheblichen Engpass in unserer Dateibereitstellungspipeline behoben. Unsere Anwendung ermöglicht es Benutzern, Tausende von Dateien, die mit einem bestimmten Ereignis verknüpft sind, als eine einzige ZIP-Datei herunterzuladen. Diese Funktion, die von einer Node.js-basierten Lambda-Funktion unterstützt wird, die für das Abrufen und Komprimieren von Dateien aus S3-Buckets verantwortlich ist, hatte mit Speicherbeschränkungen und langen Ausführungszeiten zu kämpfen, als unsere Benutzerbasis wuchs.

Dieser Beitrag beschreibt detailliert unseren Weg von einer ressourcenhungrigen Node.js-Implementierung zu einer schlanken und blitzschnellen Go-Lösung, die massive S3-Downloads effizient verarbeitet. Wir werden untersuchen, wie wir unser System optimiert haben, um Benutzern ein nahtloses Erlebnis zu bieten, wenn sie eine große Anzahl von Dateien von bestimmten Veranstaltungen anfordern, alles verpackt in einem praktischen einzigen Zip-Download.

Die Herausforderung

Unsere ursprüngliche Lambda-Funktion hatte bei der Verarbeitung großer ereignisbasierter Dateisätze mehrere kritische Probleme:

  1. Speicherverbrauch: Selbst mit 10 GB zugewiesenem Speicher würde die Funktion fehlschlagen, wenn 20.000 Dateien für größere Ereignisse verarbeitet werden.
  2. Ausführungszeit: Zip-Vorgänge für Ereignisse mit zahlreichen Dateien dauerten zu lange, manchmal kam es vor dem Abschluss zu einer Zeitüberschreitung.
  3. Skalierbarkeit: Die Funktion konnte die zunehmende Last nicht effizient bewältigen, was unsere Fähigkeit einschränkte, Benutzer mit großen Dateisätzen von beliebten Ereignissen zu bedienen.
  4. Benutzererfahrung: Langsame Download-Vorbereitungszeiten wirkten sich negativ auf die Benutzerzufriedenheit aus, insbesondere bei Ereignissen mit einer hohen Dateianzahl.

Die Node.js-Implementierung: Ein kurzer Blick

Unsere ursprüngliche Implementierung verwendete die s3-zip-Bibliothek, um ZIP-Dateien aus S3-Objekten zu erstellen. Hier ist ein vereinfachter Ausschnitt davon, wie wir Dateien verarbeitet haben:

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

// ... other code ...

const body = s3Zip.archive(
  { bucket: bucketName },
  eventId,
  files,
  entryData
);

await uploadZipFile(Upload_Bucket, zipfileKey, body);

Obwohl dieser Ansatz funktionierte, wurden alle Dateien vor dem Erstellen der ZIP-Datei in den Speicher geladen, was zu einer hohen Speicherauslastung und potenziellen Fehlern wegen unzureichendem Arbeitsspeicher bei großen Dateisätzen führte.

Geben Sie Go ein: Eine bahnbrechende Neufassung

Wir haben uns entschieden, unsere Lambda-Funktion in Go neu zu schreiben und dabei deren Effizienz und integrierte Parallelitätsfunktionen zu nutzen. Die Ergebnisse waren verblüffend:

  1. Speichernutzung: Von 10 GB auf nur noch 100 MB bei gleicher Arbeitslast gesunken.
  2. Geschwindigkeit: Die Funktion wurde etwa zehnmal schneller.
  3. Zuverlässigkeit: Verarbeitet 20.000 Dateien erfolgreich und ohne Probleme.

Wichtige Optimierungen in der Go-Implementierung

1. Effizienter S3-Betrieb

Wir haben das AWS SDK für Go v2 verwendet, das im Vergleich zu v1 eine bessere Leistung und eine geringere Speichernutzung bietet:

cfg, err := config.LoadDefaultConfig(context.TODO())
s3Client = s3.NewFromConfig(cfg)

2. Gleichzeitige Verarbeitung

Gos Goroutinen ermöglichten es uns, mehrere Dateien gleichzeitig zu verarbeiten:

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 



Dieser Ansatz ermöglicht es uns, mehrere Dateien gleichzeitig zu verarbeiten und gleichzeitig den Grad der Parallelität zu kontrollieren, um eine Überlastung des Systems zu verhindern.

3. Streaming-Zip-Erstellung

Anstatt alle Dateien in den Speicher zu laden, streamen wir den ZIP-Inhalt direkt nach 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,
})

Dieser Streaming-Ansatz reduziert die Speichernutzung erheblich und ermöglicht uns die Verarbeitung viel größerer Dateimengen.

Die Ergebnisse

Die Neufassung von Go brachte beeindruckende Verbesserungen:

  1. Speichernutzung: Reduziert um 99 % (von 10 GB auf 100 MB)
  2. Verarbeitungsgeschwindigkeit: um ca. 1000 % erhöht
  3. Zuverlässigkeit: Verarbeitet 20.000 Dateien erfolgreich und ohne Probleme
  4. Kosteneffizienz: Geringere Speichernutzung und schnellere Ausführungszeit führen zu geringeren AWS Lambda-Kosten

Gelernte Lektionen

  1. Language Choice Matters: Das Effizienz- und Parallelitätsmodell von Go hat in unserem Anwendungsfall einen gewaltigen Unterschied gemacht.
  2. Verstehen Sie Ihre Engpässe: Durch die Profilierung unserer Node.js-Funktion konnten wir wichtige Verbesserungsbereiche identifizieren.
  3. Nutzung Cloud-nativer Lösungen: Die Verwendung von AWS SDK for Go v2 und das Verständnis der S3-Funktionen ermöglichten eine bessere Integration und Leistung.
  4. Denken Sie in Streams: Die Verarbeitung von Daten als Streams, anstatt alles in den Speicher zu laden, ist für groß angelegte Vorgänge von entscheidender Bedeutung.

Abschluss

Das Umschreiben unserer Lambda-Funktion in Go hat nicht nur unsere unmittelbaren Skalierungsprobleme gelöst, sondern auch eine robustere und effizientere Lösung für unsere Dateiverarbeitungsanforderungen bereitgestellt. Obwohl Node.js uns anfangs gute Dienste leistete, verdeutlichte diese Erfahrung, wie wichtig es ist, das richtige Tool für die jeweilige Aufgabe auszuwählen, insbesondere bei der Bewältigung ressourcenintensiver Aufgaben in großem Maßstab.

Denken Sie daran, dass die beste Sprache oder das beste Framework von Ihrem spezifischen Anwendungsfall abhängt. In unserem Szenario stimmten die Leistungsmerkmale von Go perfekt mit unseren Anforderungen überein, was zu einer deutlich verbesserten Benutzererfahrung und geringeren Betriebskosten führte.

Standen Sie mit serverlosen Funktionen vor ähnlichen Herausforderungen? Wie haben Sie sie überwunden? Wir würden gerne von Ihren Erfahrungen in den Kommentaren unten hören!

Freigabeerklärung Dieser Artikel ist abgedruckt unter: https://dev.to/hiteshsisara/from-nodejs-to-go-supercreasing-s3-downloads-of-thousands-of-files-as-a-single-zip-474b?1Falls vorhanden Im Falle eines Verstoßes wenden Sie sich zum Löschen bitte an [email protected]
Neuestes Tutorial Mehr>

Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.

Copyright© 2022 湘ICP备2022001581号-3