NodeJs, introdução e conceitos centrais
Tags: node, javascript, concepts, typescript
Published: 2022-01-31 03:04:21

> Você nunca pode entender tudo, mas você deve se esforçar para entender o sistema - Ryan Dahl, criador do NodeJs

## O que é Nodejs?

Para começar vamos colocar que NodeJs, não é:

- Uma linguagem
- Um framework

NodeJs pode ser definido como um ambiente de execução (runtime) de códigos Javascript **_server-side_**. Os principais motivos para a sua adoção se dão pela fácil escalabilidade, baixo custo e flexibilidade o que torna o seu uso adequado para a programação de microsserviços e componentes de uma arquitetura _serverless_. 

Seu criador, Ryan Dahl, estava trabalhando numa feature para um sistema que se assemelhava muito com uma barra de progresso, features como essa têm a característica de consumirem muita memória e processamento, isso porque são feitas muitas operações de comunicação com o banco de dados. Naquele momento a grande maioria das plataformas faziam uso de uma abordagem de I/O baseadas em threads, isso significa que operações que precisam esperar por uma resposta, como a query feita ao banco de dados, ficam "presas" dentro de uma thread que tem o seu estado marcado como waiting. Justamente por isso o consumo de memória e processamento da aplicação subia muito, as threads precisam guardar as informações na memória, e o escalonador de processos responsável por fazer a alternância entre as threads consome um bom tempo de processamento. 

O principal diferencial do NodeJs para outras tecnologias como PHP, C# e Java é que ele é Single-Thread. Nas outras tecnologias uma thread é criada para cada requisição feita, então se uma dessas threads faz uma operação muito demorada ela vai ficar travada até o final da execução. O modelo Single-Thread é o modelo padrão, mais comum de se encontrar, mais fácil de programar, porém mais oneroso para os recursos computacionais. Já no modelo NodeJs temos apenas uma thread chamada de Event Loop, a princípio as requisições são colocadas na fila de requisições (ou também fila de eventos) e o event loop vai desempilhar cada uma dessas requisições e  tratá-las. A máquina virtual do Javascript então verifica o que tem de ser feito, delega a sua execução e volta para atender as outras requisições, quando a atividade delegada termina então ela volta para o fluxo principal para ser devolvida ao requisitante. 

![Modelo do NodeJs x Modelo Tradicional](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x9hd0xedoleu8i1b3lnh.png)

##### A analogia do restaurante

Quando um novo cliente chega num restaurante um garçom vai prontamente atendê-lo, anota o seu pedido e repassa o mesmo para o cozinheiro que começa a prepará-lo então volta para o salão para atender novos clientes que chegam, anota novos pedidos e repassa-os ao cozinheiro, esse ciclo é repetido diversas vezes, então a medida que os pedidos vão ficando prontos eles são entregues aos clientes pelo mesmo garçom. É mais ou menos assim que o Node funciona, podemos ver o garçom como o event loop e o cozinheiro como a worker pool, os clientes são os usuários de uma determinada aplicação, os pratos são os processos de regras de negócio como por exemplo, acessar o banco de dados. 

## A arquitetura NodeJs

O NodeJs é composto por componentes e cada um deles possui uma função específica, no coração dele temos o V8, uma engine Javascript usada principalmente dentro do navegador Google Chrome, ela vai ser a responsável por executar o código escrito em Javascript, então temos os NodeJs addons, código escrito em C responsável por comunicar (ligar) o V8 com o sistema operacional. Por último, e não menos importante temos a biblioteca libuv, uma biblioteca escrita em C especialmente para o NodeJs que tem como função abstrair **operações não bloqueantes de I/O**, isso permite que o CPU e outros recursos sejam usados enquanto ainda estão executando operações de entrada e saída.

![Arquitetura do NodeJs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8dnpwmggexdcaqaqzvyr.png)

## As threads dentro do NodeJs

A pesar do NodeJs ser em si Single-Thread ele faz uso de outras threads para a execução das atividades, temos dois tipos básicos de threads dentro do Node, a thread do Event Loop e as Threads do Worker Pool. 

#### Qual código é executado dentro do Event Loop?

Os aplicativos NodeJs passam pela fase de inicialização, onde fazem a solicitação dos módulos e registram os callbacks que devem ser executados quando houver a resposta dos eventos. Dentro do event loop as solicitações feitas pelas requisições são respondidas de forma síncrona. O event loop também é responsável por registrar todas as requisições assíncronas para continuar o processamento após a conclusão. Os retornos das funções assíncronas também são executados dentro do event loop.

Em resumo, o Event Loop executa os callbacks JavaScript registrados para eventos e também é responsável por atender solicitações assíncronas sem bloqueio, como entrada e saída de rede.

#### Qual código é executado dentro do worker pool?

O worker pool é implementado sobre a libuv, que expõe uma api que permite enviar tarefas, porém as tarefas reservadas ao worker pool são aquelas que são "caras" no sentido de processamento, basicamente toda e qualquer tarefa a qual o sistema operacional não fornece de forma não bloqueante. Exemplo: se um programa está consultando o banco de dados, a CPU fica ociosa até que a consulta seja processada, nesse meio tempo o programa fica parado, causando desperdício de recursos do sistema. Para evitar isso, o libuv é usado no NodeJs, o que facilita operações de I/O sem bloqueio. 

#### Como o node decide que código vai ser executado?

Através de filas, o worker pool tem uma fila que armazenas as tarefas a serem executadas, de forma com que ela pega a primeira tarefa dessa fila, trabalha nela e quando termina lança uma evento "At least one task is finished" para o event loop. Este por outro lado, na verdade, não mantém de fato uma fila, mas sim uma coleção de descritores de arquivos que juntamente com o sistema operacional monitora os eventos. Quando o sistema operacional diz que um determinado descritor de arquivo está pronto, o event loop traduz para o evento apropriado e chama o callback associado com ele. 

#### O significado para o design de aplicações

Em sistemas preemptivos que alocam uma thread por cliente como o apache, sempre que uma das threads fica em estado de bloqueado por muito tempo o sistema vai interromper a mesma e passar a vez para outra thread, outro cliente. Mas o Node é não preemptivo, isso significa que nenhuma thread é interrompida. Isso diminui muito o consumo de memória e processamento, porque diminui a incidência de troca de contexto na aplicação. 

![Comparativo entre apache e nginx](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h8muffkzg4jg9e0l4v7x.png)

Em sistemas preemptivos, onde temos um thread por cliente temos de fazer a troca de contexto com uma certa frequência, assim temos de usar muito mais memória se comparado a um sistema não preemptivo. Na imagem acima temos o apache e o nginx, esse último foi de onde o conceito de event loop foi retirado por Ryan Dahl, note que o Apache, preemptivo, que aloca uma thread por requisição, consome muito mais memória que o nginx que possui processamento paralelo. 

#### O processamento paralelo

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tnior4xvl5pucmw0835b.png)
 
A _libuv_ é uma biblioteca _cross-platform_ que permite I/O assíncrono, ela foi desenhada primeiramente para lidar com o Nodejs, mas também é usada em outros ambientes como [Julia](https://julialang.org/), [Luvit](https://luvit.io/) e uvloop. Dentre suas principais responsabilidades temos:

* Um event loop que é uportado em qualquer plataforma
* Disponibilização de sockets TCP e UDP de forma assíncrona
* Disponibilização de eventos do file system
* Controle de child processes
* Thread pool
* Signal handling

Bibliografia:

[https://www.youtube.com/watch?v=nfrVPzDJZQc](https://www.youtube.com/watch?v=nfrVPzDJZQc)

[https://stackoverflow.com/questions/36766696/which-is-correct-node-js-architecture](https://stackoverflow.com/questions/36766696/which-is-correct-node-js-architecture)

[https://www.geeksforgeeks.org/libuv-in-node-js/](https://www.geeksforgeeks.org/libuv-in-node-js/)

[https://nodejs.org/en/docs/guides/dont-block-the-event-loop/](https://nodejs.org/en/docs/guides/dont-block-the-event-loop/)