Arquitetura do Node.js: entenda o que são threads e processos
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).
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:
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):
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.