Arquitetura do Node.js: entenda o que são threads e processos

Arquitetura do Node.js: entenda o que são threads e processos
Juliana Amoasei
Juliana Amoasei

Compartilhe

Introdução

O Node.JS é composto por várias bibliotecas e APIs que, como sempre conferimos nas descrições iniciais, servem para “interpretar e executar programas em JavaScript fora do ambiente do navegador”.

Porém, é importante entendermos mais sobre como as ferramentas que usamos todos os dias funcionam mais a fundo; pois esse conhecimento nos ajuda, por exemplo, a entender alguns comportamentos inesperados e bugs em nossos programas e como corrigi-los.

Assim, para entendermos bem onde tudo se encaixa na arquitetura do Node.js vamos precisar de dois conceitos importantes em computação: threads e processos (também chamados de tasks ou tarefas).

Banner promocional da Alura, com um design futurista em tons de azul, apresentando dois blocos de texto, no qual o bloco esquerdo tem os dizeres:

O que precisamos saber sobre threads e processos

Computadores utilizam threads e processos para a execução de instruções, seja qual for a linguagem. Vamos por partes:

Processos

O que é um processo?

Podemos chamar de processo a execução (ou processamento) de um conjunto de instruções de um programa.

Normalmente, um computador tem vários processos sendo executados ao mesmo tempo - podemos pensar nos diversos programas que estão sendo continuamente executados pelo computador no background, como antivírus ou controladores de impressora - e cada processo utiliza um espaço reservado de memória. São as tais “tarefas” que acessamos com o Gerenciador de Tarefas do Windows (usando o famoso ctrl+alt+del) ou com o pacote htop do Linux.

No caso de programas executados pelo Node.js, os processos são responsáveis por “escutar” eventos e responder de acordo.

O que são eventos? O termo tem vários usos. Já falamos sobre eles anteriormente em nossa série sobre arquitetura do Node.js.

Agora que entendemos os processos no Node.js, vamos compreender o que são e como funcionam as threads.

Threads

As chamadas threads de execução são a menor unidade de processamento de um programa; são a forma como as instruções de um programa são separadas e “agendadas” para serem processadas pelo computador.

Uma tradução literal para thread seria “linha”, de acordo com o Dicionário Cambrigde, porém normalmente se usa o termo em inglês mesmo.

A quantidade de threads disponíveis para serem utilizadas por um programa depende de alguns fatores: a forma como o programa é escrito, a forma como é processado e também da capacidade da CPU do computador de processar (ou não) uma determinada quantidade de threads ao mesmo tempo.

As threads podem funcionar como componentes de um processo (o chamado parent process ou “processo pai”) e compartilhar espaços de memória entre si - ao contrário de processos que não compartilham memória - para executarem diferentes tarefas de um mesmo processo de forma mais performática.

Como uma thread de execução só pode executar uma instrução por vez (por exemplo, um laço de repetição), dividir um processo em mais de uma thread é uma estratégia para que o programa não fique “bloqueado” enquanto determinada parte dele é processada.

Você pode conferir um exemplo de processamento de um programa em várias threads na imagem a seguir:

O fluxograma apresenta três pontos de conexão com o servidor: a conexão A, B e C. O servidor divide o processamento de dados de cada uma dessas conexões em três threads diferentes. Na primeira thread, representada pelo retângulo à esquerda, há um intervalo de tempo ocioso, em seguida o "Processamento de dados de A”, depois há outro intervalo de tempo ocioso e, novamente, o "Processamento de dados de A”, na sequência a thread finaliza com mais um intervalo de tempo ocioso.Os intervalos de tempo ocioso dessa primeira thread possuem tamanhos semelhantes. Na segunda thread, representada pelo retângulo ao centro, há um grande intervalo de tempo ocioso, em seguida o “Processamento de dados de B” e finaliza com um intervalo menor de tempo ocioso. Já na terceira thread, representada pelo retângulo à direita, há um pequeno intervalo de tempo ocioso, em seguida o “Processamento de dados de C” e finaliza com um grande intervalo de tempo ocioso.

A imagem acima mostra que, ao mesmo tempo que várias threads conseguem processar dados de diversas conexões sem ter que colocá-las em uma fila, as mesmas threads também ficam ociosas enquanto não há nada acontecendo.

Agora, confira um exemplo de processamento em single thread (thread única):

O fluxograma apresenta três pontos de conexão com o servidor: a conexão A, B e C. O servidor divide o processamento de dados de cada uma dessas conexões em uma única thread. Nessa thread, representada por um único retângulo, há: um intervalo de tempo ocioso, em seguida o “Processamento de dados de A”, novamente um intervalo de tempo ocioso, em seguida o “Processamento de dados de B”, mais uma vez um intervalo de tempo ocioso, em seguida o “Processamento de dado de C”, por último há mais um intervalo de tempo ocioso. Os intervalos de tempo ocioso dessa thread possuem tamanhos semelhantes.

No exemplo acima, o processamento de cada conexão é “agendado” e colocado em fila para execução um após o outro, ao invés de serem “espalhados” por diversas threads.

Se este papo te fez lembrar de eventos síncronos e assíncronos do JavaScript, acertou! A questão de assincronicidade é essencial para a arquitetura do Node.js e também dos navegadores. Abordamos esse assunto de forma mais prática e mais voltada para código no artigo sobre programação assíncrona no JavaScript.

E neste momento você pode estar se perguntando: onde aparece o Node.js nessa história? Se quiser conferir como tudo isso se junta, confira a continuação desta série de artigos sobre a arquitetura do Node.js.

Conclusão

Neste artigo exploramos os conceitos de threads e processos, e como é feita a execução de instruções de um programa, seja em JavaScript ou qualquer outra linguagem.

Além de escrever código, é importante entendermos os demais processos e etapas que fazem com que um programa funcione, especialmente a forma como ele é executado. Isso nos ajuda a entender alguns bugs e comportamentos não esperados, como por exemplo instruções executadas na ordem “errada” e processamentos que parecem “demorar demais”.

Mas não acaba por aqui! Ainda temos bastante assunto sobre o Node.js e sua arquitetura para explorar! Você pode continuar a leitura do próximo tópico, sobre como o Node.js utiliza threads.

Juliana Amoasei
Juliana Amoasei

Desenvolvedora JavaScript com background multidisciplinar, sempre aprendendo para ensinar e vice-versa. Acredito no potencial do conhecimento como agente de mudança pessoal e social. Atuo como instrutora na Escola de Programação da Alura e, fora da tela preta, me dedico ao Kung Fu e a nerdices em geral.

Veja outros artigos sobre Programação