"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > De Node.js al futuro: sobrecargar cargas de miles de archivos como un solo zip

De Node.js al futuro: sobrecargar cargas de miles de archivos como un solo zip

Publicado el 2024-08-24
Navegar:218

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

Como desarrolladores, a menudo nos enfrentamos a desafíos cuando tratamos con el procesamiento y la entrega de datos a gran escala. En Kamero, recientemente abordamos un importante cuello de botella en nuestro proceso de entrega de archivos. Nuestra aplicación permite a los usuarios descargar miles de archivos asociados con un evento en particular como un único archivo zip. Esta característica, impulsada por una función Lambda basada en Node.js responsable de recuperar y comprimir archivos de depósitos S3, tenía problemas con limitaciones de memoria y largos tiempos de ejecución a medida que nuestra base de usuarios crecía.

Esta publicación detalla nuestro viaje desde una implementación de Node.js que consume muchos recursos hasta una solución Go eficiente y ultrarrápida que maneja de manera eficiente descargas masivas de S3. Exploraremos cómo optimizamos nuestro sistema para brindar a los usuarios una experiencia perfecta al solicitar una gran cantidad de archivos de eventos específicos, todo empaquetado en una cómoda descarga zip.

El desafío

Nuestra función Lambda original enfrentó varios problemas críticos al procesar grandes conjuntos de archivos basados ​​en eventos:

  1. Consumo de memoria: Incluso con 10 GB de memoria asignada, la función fallaría al procesar 20.000 archivos para eventos más grandes.
  2. Tiempo de ejecución: las operaciones zip para eventos con numerosos archivos tardaban demasiado y, a veces, se agotaban antes de completarse.
  3. Escalabilidad: la función no pudo manejar la carga creciente de manera eficiente, lo que limitó nuestra capacidad de brindar a los usuarios conjuntos de archivos grandes de eventos populares.
  4. Experiencia del usuario: Los tiempos de preparación de descarga lentos estaban afectando la satisfacción del usuario, especialmente para eventos con un número importante de archivos.

La implementación de Node.js: una mirada rápida

Nuestra implementación original utilizó la biblioteca s3-zip para crear archivos zip a partir de objetos S3. Aquí hay un fragmento simplificado de cómo procesamos los archivos:

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

// ... other code ...

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

await uploadZipFile(Upload_Bucket, zipfileKey, body);

Si bien este enfoque funcionó, cargó todos los archivos en la memoria antes de crear el zip, lo que provocó un uso elevado de la memoria y posibles errores de falta de memoria para conjuntos de archivos grandes.

Ingrese Go: una reescritura revolucionaria

Decidimos reescribir nuestra función Lambda en Go, aprovechando su eficiencia y sus funciones de concurrencia integradas. Los resultados fueron asombrosos:

  1. Uso de memoria: se redujo de 10 GB a solo 100 MB para la misma carga de trabajo.
  2. Velocidad: La función se volvió aproximadamente 10 veces más rápida.
  3. Confiabilidad: Procesa exitosamente 20,000 archivos sin problemas.

Optimizaciones clave en la implementación de Go

1. Operaciones S3 eficientes

Utilizamos AWS SDK para Go v2, que ofrece un mejor rendimiento y un menor uso de memoria en comparación con v1:

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

2. Procesamiento simultáneo

Las gorutinas de Go nos permitieron procesar varios archivos simultáneamente:

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 



Este enfoque nos permite procesar varios archivos simultáneamente mientras controlamos el nivel de simultaneidad para evitar sobrecargar el sistema.

3. Creación de archivos zip en streaming

En lugar de cargar todos los archivos en la memoria, transmitimos el contenido zip directamente a 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,
})

Este enfoque de transmisión reduce significativamente el uso de memoria y nos permite manejar conjuntos de archivos mucho más grandes.

Los resultados

La reescritura de Go proporcionó mejoras impresionantes:

  1. Uso de memoria: Reducido en un 99% (de 10 GB a 100 MB)
  2. Velocidad de procesamiento: Incrementada aproximadamente un 1000%
  3. Confiabilidad: maneja con éxito 20.000 archivos sin problemas
  4. Eficiencia de costos: un menor uso de memoria y un tiempo de ejecución más rápido dan como resultado costos reducidos de AWS Lambda

Lecciones aprendidas

  1. La elección del idioma importa: El modelo de eficiencia y concurrencia de Go marcó una gran diferencia en nuestro caso de uso.
  2. Comprenda sus cuellos de botella: crear perfiles de nuestra función Node.js nos ayudó a identificar áreas clave para mejorar.
  3. Aproveche las soluciones nativas de la nube: el uso de AWS SDK for Go v2 y la comprensión de las capacidades de S3 permitieron una mejor integración y rendimiento.
  4. Piense en secuencias: Procesar datos como secuencias en lugar de cargar todo en la memoria es crucial para operaciones a gran escala.

Conclusión

Reescribir nuestra función Lambda en Go no solo resolvió nuestros problemas de escalado inmediatos, sino que también proporcionó una solución más sólida y eficiente para nuestras necesidades de procesamiento de archivos. Si bien Node.js nos resultó útil al principio, esta experiencia destacó la importancia de elegir la herramienta adecuada para el trabajo, especialmente cuando se trata de tareas que consumen muchos recursos a escala.

Recuerde, el mejor lenguaje o marco depende de su caso de uso específico. En nuestro escenario, las características de rendimiento de Go se alinearon perfectamente con nuestras necesidades, lo que resultó en una experiencia de usuario significativamente mejorada y costos operativos reducidos.

¿Ha enfrentado desafíos similares con funciones sin servidor? ¿Cómo los superaste? ¡Nos encantaría conocer tus experiencias en los comentarios a continuación!

Declaración de liberación Este artículo se reproduce en: https://dev.to/hiteshsisara/from-nodejs-to-go-supercharging-s3-downloads-of-thousands-of-files-as-a-single-zip-474b?1Si hay Si hay alguna infracción, comuníquese con [email protected] para eliminar
Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3