"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Do Node.js ao Go: supercarregando milhares de arquivos como um único Zip

Do Node.js ao Go: supercarregando milhares de arquivos como um único Zip

Publicado em 2024-08-24
Navegar:562

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

Como desenvolvedores, frequentemente enfrentamos desafios ao lidar com processamento e entrega de dados em grande escala. Na Kamero, recentemente resolvemos um gargalo significativo em nosso pipeline de entrega de arquivos. Nosso aplicativo permite aos usuários baixar milhares de arquivos associados a um evento específico como um único arquivo zip. Esse recurso, desenvolvido por uma função Lambda baseada em Node.js, responsável por buscar e compactar arquivos de buckets S3, enfrentava restrições de memória e longos tempos de execução à medida que nossa base de usuários crescia.

Esta postagem detalha nossa jornada de uma implementação Node.js que consome muitos recursos até uma solução Go enxuta e extremamente rápida que lida com eficiência com downloads massivos de S3. Exploraremos como otimizamos nosso sistema para fornecer aos usuários uma experiência perfeita ao solicitar um grande número de arquivos de eventos específicos, todos empacotados em um conveniente download zip único.

O desafio

Nossa função Lambda original enfrentou vários problemas críticos ao processar grandes conjuntos de arquivos baseados em eventos:

  1. Consumo de memória: mesmo com 10 GB de memória alocada, a função falharia ao processar 20.000 arquivos para eventos maiores.
  2. Tempo de execução: as operações zip para eventos com vários arquivos estavam demorando muito, às vezes expirando antes da conclusão.
  3. Escalabilidade: a função não conseguiu lidar com a carga crescente de forma eficiente, limitando nossa capacidade de atender aos usuários grandes conjuntos de arquivos de eventos populares.
  4. Experiência do usuário: os tempos lentos de preparação para download estavam afetando a satisfação do usuário, especialmente para eventos com contagens substanciais de arquivos.

A implementação do Node.js: uma visão rápida

Nossa implementação original usou a biblioteca s3-zip para criar arquivos zip a partir de objetos S3. Aqui está um trecho simplificado de como estávamos processando os arquivos:

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

// ... other code ...

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

await uploadZipFile(Upload_Bucket, zipfileKey, body);

Embora essa abordagem tenha funcionado, ela carregou todos os arquivos na memória antes de criar o zip, levando a um alto uso de memória e possíveis erros de falta de memória para conjuntos de arquivos grandes.

Enter Go: uma reescrita revolucionária

Decidimos reescrever nossa função Lambda em Go, aproveitando sua eficiência e recursos de simultaneidade integrados. Os resultados foram surpreendentes:

  1. Uso de memória: caiu de 10 GB para apenas 100 MB para a mesma carga de trabalho.
  2. Velocidade: A função ficou aproximadamente 10 vezes mais rápida.
  3. Confiabilidade: processa com êxito 20.000 arquivos sem problemas.

Principais otimizações na implementação Go

1. Operações S3 eficientes

Usamos o AWS SDK for Go v2, que oferece melhor desempenho e menor uso de memória em comparação com v1:

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

2. Processamento Simultâneo

As goroutines do Go nos permitiram processar vários arquivos simultaneamente:

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 



Essa abordagem nos permite processar vários arquivos simultaneamente enquanto controlamos o nível de simultaneidade para evitar sobrecarregar o sistema.

3. Criação de Zip de streaming

Em vez de carregar todos os arquivos na memória, transmitimos o conteúdo zip diretamente para o 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,
})

Essa abordagem de streaming reduz significativamente o uso de memória e nos permite lidar com conjuntos de arquivos muito maiores.

Os resultados

A reescrita para Go proporcionou melhorias impressionantes:

  1. Uso de memória: reduzido em 99% (de 10 GB para 100 MB)
  2. Velocidade de processamento: aumentada em aproximadamente 1000%
  3. Confiabilidade: lida com sucesso com 20.000 arquivos sem problemas
  4. Eficiência de custos: menor uso de memória e tempo de execução mais rápido resultam em custos reduzidos do AWS Lambda

Lições aprendidas

  1. A escolha do idioma é importante: a eficiência e o modelo de simultaneidade do Go fizeram uma enorme diferença em nosso caso de uso.
  2. Entenda seus gargalos: Criar o perfil de nossa função Node.js nos ajudou a identificar áreas-chave para melhoria.
  3. Aproveite as soluções nativas da nuvem: usar o AWS SDK for Go v2 e compreender os recursos do S3 permitiu melhor integração e desempenho.
  4. Pense em Streams: Processar dados como streams em vez de carregar tudo na memória é crucial para operações em grande escala.

Conclusão

Reescrever nossa função Lambda em Go não apenas resolveu nossos problemas imediatos de escalabilidade, mas também forneceu uma solução mais robusta e eficiente para nossas necessidades de processamento de arquivos. Embora o Node.js tenha nos servido bem inicialmente, essa experiência destacou a importância de escolher a ferramenta certa para o trabalho, especialmente ao lidar com tarefas que exigem muitos recursos em grande escala.

Lembre-se de que a melhor linguagem ou estrutura depende do seu caso de uso específico. Em nosso cenário, as características de desempenho do Go se alinharam perfeitamente às nossas necessidades, resultando em uma experiência de usuário significativamente melhorada e custos operacionais reduzidos.

Você enfrentou desafios semelhantes com funções sem servidor? Como você os superou? Adoraríamos ouvir sobre suas experiências nos comentários abaixo!

Declaração de lançamento Este artigo é reproduzido em: https://dev.to/hiteshsisara/from-nodejs-to-go-supercharging-s3-downloads-of-thils-of-files-as-a-single-zip-474b?1 Se houver alguma infração, entre em contato com [email protected] para Delete.
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3