Trabalhando com Multithreading e Streaming no NodeJs – Parte 1

Trabalhando com Multithreading e Streaming no NodeJs – Parte 1

O Node.js é uma das tecnologias que mais chama a atenção por ser rápido, leve e poderoso, além de permitir o desenvolvimento de aplicações escaláveis e tolerantes a falhas. Contudo, em alguns cenários um pouco mais substanciais devemos olhar com mais atenção para a maneira como se trabalha com essa tecnologia.

Imagine que você como desenvolvedor, precisa construir um serviço de importação de arquivos e nele ainda precisa ter alguns endpoints específicos, considerando esse cenário vamos imaginar que o serviço precisa terendpoints. O primeiro é para solicitar a importação de um arquivo e o segundo é para reportar o status da importação de algum arquivo. Isto é, além de baixar e ler o arquivo, o serviço ainda precisa responder requests que podem vir com certa frequência.

Agora imagine que esse serviço foi desenvolvido da maneira “tradicional” sem nenhuma preocupação com performance e disponibilidade, em determinado dia o serviço que desenvolvemos recebeu uma solicitação para baixar e ler um arquivo csv grande e digamos que ele tenha pelo menos 7 GB, até aqui tudo bem, o serviço foi feito para realizar a importação independente do tamanho, porém, neste mesmo momento, os usuários começam a reportar que o serviço parou de responder e ninguém está conseguindo importar outro arquivo ou consultar o status das suas importações. Isso aconteceu porque o Node é orientado a eventos e utiliza o conceito de thread única para gerenciar a pilha de eventos ou pilha de chamada (Call Stack), ou seja, todas as solicitações são processadas uma a uma, através de uma camada de processamento enquanto o arquivo de 7GB está sendo importado, nenhuma outra solicitação ao nosso serviço vai ser respondida.

É em cenários assim que nós como desenvolvedores devemos começar a pensar em trabalhar com multi-threading, isto é, criar threads secundárias e paralelas a thread principal que vão executar serviços que deixem a threads  principal livre para responder a outras solicitações. Essas threads secundárias são chamadas de workers, que são processos em background de I/O assíncrono não bloqueastes gerenciados pela libuv, uma biblioteca open source multiplataforma escrita em linguagem C, a qual utiliza um thread-pool para gerenciar operações paralelas. Pensando nisso, vamos ver como trabalhar com multi-threading no node.

Primeiramente, vamos precisar trabalhar com a API nativa do node chamada worker_threads, conforme o exemplo abaixo:

const { Worker } = require("worker_threads");

Em seguida, devemos criar um arquivo javascript com a lógica que queremos implementar para realizar a importação do arquivo. Por enquanto vamos deixar a lógica e a regra para um próximo artigo, onde aprenderemos a trabalhar com streaming de arquivos.

~ worker.js

const { workerData } = require("worker_threads");

const importFile = (file) => {
  // Lógica de importação
  console.log(file);
  return true;
}

importFile(workerData.file);

Em seguida, voltamos ao arquivo anterior, onde criamos a instância do worker, passando o arquivo que acabamos de criar:

//Criando um novo worker
const worker = new Worker("./worker.js", { workerData: { file }});

//Listeners
worker.once("message", result => {
  console.log(result);
});

worker.on("error", error => {
  console.log(error);
});

worker.on("exit", exitCode => {
  console.log(exitCode);
});

Já configuramos também alguns listeners que vamos usar para capturar as mensagens que podem vir do nosso processo rodando em threads secundárias. Usaremos para receber mensagens de erro e atualização de progresso de importação.

Com esses três trechos de código bem simples, já conseguimos separar os processos em várias threads, deixando a thread principal livre para responder a outras solicitações e assim evitamos problemas de disponibilidade do nosso serviço.

No próximo artigo veremos como realizar a importação do arquivo usando stream e como reportar as mensagens de erro e progresso da importação para a thread principal.

A Seguir:

  • Trabalhando com multithreading e streaming no NodeJs – Parte 2
  • Design Patterns: Strategy

Links Úteis

Deixe um comentário

O seu endereço de e-mail não será publicado.

Open chat
1
Posso ajudar?
Olá,
Podemos te ajudar?
R. Alvorada, 1289 - CJ 615 - Vila Olímpia, São Paulo - SP, 04550-004