Cluster: como usar todos os núcleos da sua CPU

Cluster: como usar todos os núcleos da sua CPU

Robson Rabelo - 12 de julho de 2026 - 3 visualizações

Um núcleo a 100% e sete dormindo: o módulo cluster do Node.js em 20 linhas, os bônus (tolerância a falha, deploy sem downtime) e as pegadinhas que separam demo de produção.

Você provisionou um servidor de 8 núcleos para sua API Node.js. Abra o monitor de recursos num pico de tráfego e prepare-se para a cena do crime: um núcleo a 100%, sete dormindo. Você está pagando por oito e usando um.

Não é bug; é design. Como vimos no artigo do event loop, o JavaScript do Node roda numa única thread, portanto num único núcleo. O módulo cluster existe exatamente para essa conta fechar: um processo Node por núcleo, todos dividindo a mesma porta.

Como funciona por baixo

O modelo é primário/trabalhadores (primary/workers): o processo primário não atende requisições; ele forca N cópias da aplicação e distribui as conexões entre elas. Cada worker é um processo completo, com seu próprio event loop, sua própria memória e seu próprio V8.

O truque da porta compartilhada: quando um worker chama server.listen(3000), o Node percebe que ele é um worker e, em vez de abrir a porta, pede o socket ao primário. No Linux, por padrão, o primário aceita as conexões e as distribui em round-robin entre os workers (documentação oficial).

// server.js
const cluster = require("node:cluster");
const os = require("node:os");

if (cluster.isPrimary) {
  const n = os.availableParallelism(); // núcleos disponíveis
  console.log(`Primário ${process.pid}: subindo ${n} workers`);

  for (let i = 0; i < n; i++) cluster.fork();

  cluster.on("exit", (worker, code) => {
    console.log(`Worker ${worker.process.pid} morreu (${code}). Repondo...`);
    cluster.fork(); // auto-recuperação: worker que cai é substituído
  });
} else {
  // Cada worker roda a aplicação completa
  require("./app"); // seu Express/Fastify com app.listen(3000)
}

Vinte linhas, e a API passa a usar a máquina inteira. Num servidor de 8 núcleos, o ganho de throughput em cargas típicas de API fica próximo do linear.

Os bônus que vêm de graça

  • Tolerância a falha: uma exceção não tratada derruba um worker, não o serviço. O primário repõe em milissegundos, e os outros 7 seguem atendendo. É o MTTR despencando por arquitetura.
  • Deploy sem downtime: reinicie os workers um por vez (rolling restart): o serviço nunca fica fora do ar durante o deploy. Ferramentas de processo como o PM2 empacotam isso num comando (pm2 reload), com o modo cluster embutido (pm2.keymetrics.io).
  • Isolamento de bloqueio: aquele endpoint que bloqueia o event loop por 200ms agora trava 1/8 da capacidade, não 100%.

Cluster: um processo por núcleo, uma porta

As pegadinhas (a parte que separa a demo da produção)

1. Nada de estado em memória. Cada worker tem sua própria memória. Sessão guardada num objeto? O usuário loga no worker 3 e "desloga" ao cair no worker 5. Cache em variável? Oito versões divergentes. A regra: estado compartilhado sai do processo: sessões e cache no Redis, e o processo fica descartável (como todo o resto).

2. WebSockets pedem sessão pegajosa. Handshakes de Socket.IO com polling precisam cair sempre no mesmo worker (sticky sessions), ou a conexão quebra. As soluções: adapter de Redis + sticky no balanceador, ou transporte só-websocket.

3. Multiplicou processos, multiplicou conexões. Oito workers × pool de 10 conexões de banco = 80 conexões. Dimensione o pool por worker dividindo o limite total, ou o banco recusa conexão no pico.

4. Memória se multiplica também. Cada worker carrega a aplicação inteira. App de 300MB × 8 = 2,4GB. Ajuste o número de workers à memória disponível, não só aos núcleos.

Cluster, Worker Threads ou Kubernetes?

A dúvida clássica, com resposta direta:

  • Cluster: escala requisições (I/O) pelos núcleos de uma máquina. É o padrão para APIs.
  • Worker Threads: escala cálculo (CPU) sem multiplicar o processo inteiro; ideal para tarefas pesadas pontuais (próximo artigo da série).
  • Kubernetes/containers: escala em várias máquinas. E aqui um detalhe de arquitetura moderna: se você roda um container por pod com limite de 1 CPU, o cluster interno vira redundância; deixe o orquestrador replicar. Cluster brilha em VMs e máquinas dedicadas com muitos núcleos.

Os três se combinam: cluster dentro da VM, réplicas no orquestrador, workers para o cálculo pesado. O desenho certo depende de onde sua aplicação roda, exatamente o tipo de decisão que ajustamos no serviço de Desenvolvimento Web, Mobile e Desktop.

Quantos núcleos sua API está desperdiçando agora? Rode os.availableParallelism() e compare com seus processos. Depois conte para a IA da Rabelo Digital, aqui no canto da tela, e ela desenha o plano. Sem formulário, sem espera.


Leia também

Compartilhar:

Deixe um Comentário

Categorias

Posts Recentes