Circuit Breaker: Protegendo Sistemas Distribuídos Contra Falhas em Cascata
Esse conteúdo foi retirado da plataforma https://dinamos.net
Circuit Breaker: Protegendo Sistemas Distribuídos Contra Falhas em Cascata
Introdução
O Circuit Breaker (Disjuntor) é um padrão de design fundamental em sistemas distribuídos, funcionando de maneira análoga a um disjuntor elétrico. Sua principal função é prevenir falhas em cascata, permitindo que sistemas se recuperem automaticamente de situações de erro.
Como Funciona
O Circuit Breaker monitora as chamadas entre serviços e atua como um intermediário que pode interromper o fluxo de requisições quando necessário. Ele opera em três estados distintos:
stateDiagram-v2
[] --> Fechado
Fechado --> Aberto: Muitas falhas
Aberto --> SemiAberto: Timeout
SemiAberto --> Fechado: Sucesso
SemiAberto --> Aberto: Falha
Estados do Circuit Breaker
-
Fechado (Normal)
- Estado padrão
- Requisições passam normalmente
- Monitora taxa de falhas
- Conta falhas em uma janela de tempo
-
Aberto (Bloqueado)
- Ativado após muitas falhas
- Rejeita todas as requisições
- Inicia timer de timeout
- Falha rápido sem consumir recursos
-
Semi-Aberto (Teste)
- Estado de teste após timeout
- Permite algumas requisições
- Monitora resultados
- Decide próximo estado
Implementação
Exemplo de implementação básica em TypeScript:
class CircuitBreaker {
private state: "CLOSED" | "OPEN" | "HALF_OPEN" = "CLOSED";
private failureCount: number = 0;
private failureThreshold: number = 5;
private resetTimeout: number = 60000; // 60 segundos
private lastFailureTime: number = 0;
async execute(operation: () => Promise<any>): Promise<any> {
if (this.shouldAllowRequest()) {
try {
const result = await operation();
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
} else {
throw new Error("Circuit Breaker is OPEN");
}
}
private shouldAllowRequest(): boolean {
if (this.state === "CLOSED") return true;
if (this.state === "OPEN") {
if (Date.now() - this.lastFailureTime >= this.resetTimeout) {
this.state = "HALF_OPEN";
return true;
}
return false;
}
return true; // HALF_OPEN permite algumas requisições
}
private onSuccess(): void {
if (this.state === "HALF_OPEN") {
this.state = "CLOSED";
this.failureCount = 0;
}
}
private onFailure(): void {
this.failureCount++;
this.lastFailureTime = Date.now();
if (this.failureCount >= this.failureThreshold) {
this.state = "OPEN";
}
}
}
Configurações Importantes
graph TD
A[Circuit Breaker] --> B[Threshold]
A --> C[Timeout]
A --> D[Fallback]
B --> E[Número de falhas]
B --> F[Janela de tempo]
C --> G[Tempo de reset]
C --> H[Tempo de espera]
D --> I[Resposta padrão]
D --> J[Cache]
Parâmetros Configuráveis
-
Threshold de Falhas
- Número de falhas permitidas
- Janela de tempo para contagem
- Taxa de erro aceitável
-
Timeouts
- Tempo de espera por resposta
- Período de reset do circuito
- Intervalo entre tentativas
-
Estratégias de Fallback
- Respostas em cache
- Valores padrão
- Rotas alternativas
Exemplo do Mundo Real
Considere um serviço de e-commerce com múltiplos microsserviços:
sequenceDiagram
participant Cliente
participant API Gateway
participant Serviço de Produtos
participant Serviço de Preços
participant Circuit Breaker
Cliente->>API Gateway: Busca produto
API Gateway->>Circuit Breaker: Verifica estado
alt Circuit Breaker Fechado
Circuit Breaker->>Serviço de Produtos: Requisição
Serviço de Produtos->>Serviço de Preços: Busca preço
Serviço de Preços-->>Serviço de Produtos: Timeout
Serviço de Produtos-->>Circuit Breaker: Erro
Circuit Breaker->>Circuit Breaker: Incrementa falhas
else Circuit Breaker Aberto
Circuit Breaker-->>API Gateway: Rejeita requisição
API Gateway-->>Cliente: Fallback (cache)
Cenário
- O serviço de preços começa a falhar
- Circuit Breaker detecta falhas consecutivas
- Circuito abre, protegendo o sistema
- API retorna preços em cache
- Após timeout, testa recuperação
Benefícios
-
Resiliência
- Previne falhas em cascata
- Permite recuperação automática
- Isola componentes problemáticos
-
Performance
- Falha rápido quando necessário
- Reduz latência em falhas
- Economiza recursos
-
Monitoramento
- Facilita detecção de problemas
- Fornece métricas claras
- Ajuda no diagnóstico
Melhores Práticas
-
Configuração
- Ajuste thresholds por contexto
- Use timeouts apropriados
- Implemente fallbacks relevantes
-
Monitoramento
- Monitore estados do circuito
- Colete métricas de falhas
- Alerte em mudanças de estado
-
Implementação
- Use bibliotecas testadas
- Implemente por domínio
- Considere contexto da aplicação
Conclusão
O Circuit Breaker é essencial para construir sistemas distribuídos resilientes. Sua implementação adequada pode prevenir falhas catastróficas e melhorar significativamente a experiência do usuário em cenários de erro.
Recursos Adicionais
Muito massa! Eu implementei isso no programa de fidelidade no ecommerce da empresa onde trabalho. É muito útil e faz com que nao atole um serviço com um momte de requests caso ele caia. Aqui use uma lib pra PHP chamada Ganesha.