Circuit Breaker: O Padrão de Design que Você Precisa Conhecer
Profile picture

Junior Alves

Senior Developer

Foto: Unsplash

9 de junho de 20256 minutos de leitura

Circuit Breaker: O Padrão de Design que Você Precisa Conhecer

O Guia Completo para Proteger Seus Sistemas Contra Falhas em Cascata (com Node.js)

Introdução

Imagine que é Black Friday. Um usuário clica em "Finalizar compra" no seu e-commerce. A página carrega, carrega... e da erro. O que aconteceu? O serviço de pagamentos, um microserviço externo, ficou lento e parou de responder.

Como o seu serviço de Checkout vai responder à essa situação?
Vai ficar dando retry eternamente, consumindo recursos (memória, conexões do banco, ...)?!
E se quando o Checkout parar de responder, o serviço de Carrinho e Estoque vão parar também?
Bom, é nesse cenário de caos e problemas/falhas em cascata, que brilha um conceito simples, porém muito poderoso.

Ahhh, e o mais interessante, você já até sabe a teoria por trás dele.

O Disjuntor

Sabe o disjuntor da sua casa (espero que você tenha um 🙏)? Então, o que acontece se você ligar muitos aparelhos ao mesmo tempo em uma única tomada? Sobrecarga, certo? Nesse cenário, o disjuntor é disparado para proteger a fiação da sua casa de superaquecer e causar um incêndio. Ele basicamente interrompe o fluxo de eletricidade para o circuito problemático. Os aparelhos param de funcionar, mas o resto da sua casa continua com energia, pois o problema foi contido. E por fim, para a energia voltar, você precisa ir até a caixa de luz e manualmente rearmar o disjuntor, isso claro, antes você antes deve desligar alguns aparelhos (resolver a causa da sobrecarga).

O Circuit Breaker

Ele é basicamente o disjuntor, mas no ambiente de software. Ahhh, ele faz isso de forma automática. Pense no Circuit Breaker como um Wrapper que você coloca em volta de chamadas a um serviço externo que pode falhar.

Como o Circuit Breaker funciona?

O Circuit Breaker tem basicamente 3 estados:

  1. 🟢 CLOSED (Fechado)
  • Esse é o estado default. A "eletricidade está fluindo".
  • O Circuit Breaker fica monitorando as chamadas. Se uma falha acontecer (timeout, erro 500, ...), ele anota.
  1. 🔴 OPEN (Aberto)
  • Esse é o estado "disparado".
  • Quando acontece? Ele dispara e muda de CLOSED para OPEN quando o número de falhas atinge um limite que você configurou. Vamos ver na prática daqui a pouco.
  • Enquanto está OPEN, ele não tenta mais fazer a chamada de rede para o serviço. Ele já falha imediatamente, retornando um erro.
  1. 🟡 HALF-OPEN (Meio-Aberto)
  • Após um tempo configurado no estado OPEN, o Circuit Breaker não volta direto para o CLOSED. Ele volta com cautela, em HALF-OPEN

  • Ele age como um "teste". Ele permite que uma única requisição passe para o serviço que está com falha.

  • Se essa request retornar sucesso, ele assume que o sistema voltou, alterando seu estado para CLOSED e o fluxo de requests normaliza.

  • Se essa request de teste falha, ele volta imediatamente para o estado OPEN, e inicia um novo período de espera.

Mão na massa: Implementando Circuit Breaker em Node.js

Chega de teoria, vamos para o código! E ao invés de reinventar a roda, vamos usar uma lib para nos ajudar, a Opossum.

Passo 1: Preparando o ambiente

mkdir circuit-breaker-example
cd circuit-breaker-example
npm init -y
npm install express opossum

Passo 2: Criando o vilão (nosso serviço instável)

// unstableService.js
function pay() {
  return new Promise((resolve, reject) => {
    // Simula uma falha em 50% das vezes
    const shouldFail = Math.random() > 0.5;
    setTimeout(() => {
      if (shouldFail) {
        console.log('❌ Pagamento Falhou!');
        reject(new Error('Serviço de pagamento indisponível.'));
      } else {
        console.log('✅ Pagamento Realizado com Sucesso!');
        resolve({ status: 'Aprovado' });
      }
    }, 1000); // Simula latência de rede
  });
}
 
module.exports = { pay };

Passo 3: Criando o Circuit Breaker

  • Crie o arquivo principal index.js.
// index.js
const express = require('express');
const Opossum = require('opossum');
const { pay } = require('./unstableService');
 
const app = express();
const PORT = 3000;
 
// 1. Configuração do Circuit Breaker
const options = {
  timeout: 3000, // Se a função demorar mais que 3s, falha
  errorThresholdPercentage: 50, // Dispara se 50% das requests falharem
  resetTimeout: 30000 // Tenta se recuperar após 30s
};
 
const breaker = new Opossum(pay, options);
 
// 2. Definindo o "Fallback"
// O que fazer quando o circuito está aberto?
breaker.fallback(() => ({
  status: 'Fallback',
  message: 'Serviço de pagamento indisponível no momento. Tente novamente mais tarde.'
}));
 
// 3. Monitorando os eventos do Breaker (ótimo para logs!)
breaker.on('open', () => console.log(`CIRCUITO ABERTO: O breaker disparou.`));
breaker.on('halfOpen', () => console.log(`CIRCUITO MEIO-ABERTO: Testando a recuperação...`));
breaker.on('close', () => console.log(`CIRCUITO FECHADO: O serviço se recuperou.`));
breaker.on('fallback', (result) => console.log(`FALLBACK: Executado com o resultado: ${result.message}`));
 
 
// 4. Nossa rota de Checkout que usa o Breaker
app.get('/checkout', async (req, res) => {
  console.log('\n--- Nova Tentativa de Checkout ---');
  try {
    const result = await breaker.fire();
    console.log('Resultado da operação:', result);
    res.json(result);
  } catch (err) {
    console.error('Erro na chamada:', err.message);
    res.status(500).json({ error: err.message });
  }
});
 
app.listen(PORT, () => {
  console.log(`Servidor rodando na porta ${PORT}.`);
  console.log('Acesse http://localhost:3000/checkout para testar.');
});

Passo 4: Testando e Observando

Instrua o leitor a rodar node index.js e acessar http://localhost:3000/checkout várias vezes (usando o navegador ou uma ferramenta como o curl).

  • Peça para ele observar o console:
    • No início, as chamadas vão variar entre sucesso e falha.
    • Após algumas falhas, ele verá a mensagem "CIRCUITO ABERTO".
    • A partir daí, todas as chamadas serão instantaneamente rejeitadas e a mensagem de fallback será exibida.
    • Após 30 segundos, ele verá "CIRCUITO MEIO-ABERTO".
    • Se a próxima chamada funcionar, o circuito fechará. Se falhar, ele abrirá novamente.

Pratique para fixar 🎉

Qual é o principal problema que o padrão Circuit Breaker foi projetado para resolver em sistemas distribuídos?

1 / 5

Conclusão

Chegamos ao fim da nossa jornada e agora você tem um novo superpoder: a resiliência. O Circuit Breaker é como aquele herói que atua nos bastidores para garantir que o show continue, mesmo quando um dos atores principais falha.

Lembre-se dos ganhos que ele traz para o seu projeto:

  • Adeus, efeito dominó: Ele é o guarda que impede que uma pequena falha cause uma catástrofe em todo o seu ecossistema de microserviços.
  • Usuários mais felizes: Ninguém gosta de esperar. O fail-fast (falha rápida) do Circuit Breaker oferece uma experiência muito mais agradável do que o suspense de uma requisição que nunca termina.
  • Sistemas que se curam: Você cria um ambiente inteligente onde os componentes têm a chance de se recuperar sozinhos, sem que você precise intervir manualmente no meio da madrugada.

Muito obrigado por ler até aqui, espero ter ajudado a entender sobre o Circuit Breaker. Qualquer dúvida ou sugestão é sempre bem vinda nos comentários!

Até o próximo post 🚀

Curtiu? Compartilhe esse post:

Todos os direitos reseverdos © Junior Alves 2025