Arquitetura do Node.js: o Node.js é single-threaded?
Introdução
Caso você já esteja estudando a arquitetura do Node.JS, pode ter se deparado com a informação: “o Node.js é single-thread”. Mas o que exatamente isso significa? O que define se um programa é processado em single threads ou multi threads?
Vamos entender mais sobre o caso específico do Node.js.
O Node.js é single-threaded?
O Node.js não é apenas um programa e sim um controlador que engloba algumas bibliotecas e APIs. Então onde a questão das threads entra nisso?
Perdeu esta parte? Confira nosso artigo sobre as partes que compõem o Node.js.
Todo código em JavaScript executado por um programa, inclusive o código em JavaScript que existe dentro do código-fonte do próprio Node.js, o V8, o loop de eventos e métodos síncronos em C++ que existem dentro do Node.js são executados na mesma thread, chamada de main thread (thread principal). Por isso é dito que o Node.js é single-threaded.
E o que o C++ está fazendo no Node.js, não estamos falando de JavaScript? Na verdade, o Node.js é um programa escrito em C++, assim como a libuv. Além desse exemplo, também existem outras APIs orquestradas internamente pelo Node.js que utilizam, por baixo dos panos, métodos escritos em C++.
Então, alguns métodos e módulos assíncronos em C++, que são utilizados pelo Node.js, podem não ser executados na main thread, como por exemplo o módulo crypto
, que utiliza muito processamento da CPU e precisa fazer muitos cálculos matemáticos. Em casos como esse, o C++ vai executar métodos assíncronos, por baixo dos panos, utilizando mais de uma thread se for necessário, a chamada “execução em paralelo”.
O Node.js utiliza a libuv para operações assíncronas; essa biblioteca também é utilizada, junto com parte da lógica interna do Node.js para manejar a chamada thread pool, que são quatro threads pré-alocadas por padrão e usadas para delegar operações muito “pesadas” (exigem muito processamento) para serem colocadas no loop de eventos. Por exemplo: algumas operações de I/O, iniciar e fechar conexões (como socket.close()
) e manejar timers como setTimeout()
.
O termo “pool” (piscina) é bastante abrangente em programação; pode ser usado para designar um conjunto de recursos computacionais que estão prontos para uso e à disposição do programa. No caso de threads, podemos entender uma thread pool como um conjunto de threads que já foram criadas “de antemão” pelo programa e ficam em “stand by”.
Assim, é dito que o Node.js é single-threaded pois algumas de suas partes essenciais - entre elas o loop de eventos - trabalha de forma single thread. Porém, partes do processamento de um programa podem ser trabalhadas de forma multi-thread pela libuv, utilizando a thread pool, além de métodos em C++ que podem ser delegados ao sistema operacional para o processamento adicional de tarefas mais complexas.
Alguns processos devem necessariamente operar em single thread, pegando os retornos de forma ordenada para evitar que, por exemplo, duas threads alterem a mesma variável. É o caso do loop de eventos.
Conclusão
Neste artigo exploramos a ideia de single thread e como isso é aplicado no Node.js. Uma vez que entendemos o Node.js não como um programa único, mas como um “controlador” que chama outras bibliotecas e maneja os dados retornados, temos uma ideia melhor do que isso significa.
Ao entendermos melhor a forma como o Node.js trabalha, podemos entender como vai ser feita a execução de nossos programas e o processamento dos dados, e assim tentar prever comportamentos não esperados ou resolver bugs com mais agilidade.
Você chegou ao final deste artigo, mas 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.
Bons estudos!