Circuit Breaker
Em uma arquitetura de microserviços, as falhas são inevitáveis. Uma API lenta ou um banco de dados fora do ar podem gerar um efeito dominó que derruba todo o seu ecossistema. O Circuit Breaker (Disjuntor) é a proteção que evita que uma pequena falha se torne um desastre total.
A Analogia do Disjuntor Elétrico
Na sua casa, o disjuntor desarma quando há uma sobrecarga, protegendo os seus aparelhos. No software, o Circuit Breaker interrompe chamadas a um serviço que está falhando, protegendo o seu sistema de ficar travado esperando respostas que não virão.
stateDiagram-v2
direction LR
[*] --> CLOSED
CLOSED --> OPEN: Falhas > Limite
OPEN --> HALF_OPEN: Tempo de espera esgotado
HALF_OPEN --> CLOSED: Sucesso nos testes
HALF_OPEN --> OPEN: Falha nos testes
Os 3 Estados do Disjuntor
- Closed (Fechado): O sistema está saudável. As requisições passam normalmente. O disjuntor fica monitorando a taxa de erros.
- Open (Aberto): O limite de erros foi atingido. O disjuntor “abre” e bloqueia imediatamente todas as chamadas. Ele retorna um erro rápido ou um valor padrão (fallback) sem nem tentar chamar o serviço instável.
- Half-Open (Meio Aberto): Após um tempo de espera, o disjuntor deixa passar algumas requisições de teste para ver se o serviço voltou ao normal. Se funcionar, ele fecha; se falhar, ele abre novamente.
Exemplo Prático com Resilience4j (Spring Boot)
1
2
3
4
5
6
7
8
9
@CircuitBreaker(name = "paymentService", fallbackMethod = "fallbackPayment")
public PaymentResponse process(PaymentRequest request) {
return restTemplate.postForObject("/payments", request, PaymentResponse.class);
}
// O que acontece se o serviço de pagamentos estiver fora do ar
public PaymentResponse fallbackPayment(PaymentRequest request, Throwable t) {
return new PaymentResponse("PENDING", "Sistema temporariamente indisponível. Tente mais tarde.");
}
Por que usar?
- Liberação de Recursos: Evita que suas threads fiquem presas esperando timeouts longos.
- User Experience: É melhor retornar um erro rápido ou um dado em cache do que deixar o usuário vendo um “loading” infinito.
- Recuperação do Serviço Falho: Ao parar de enviar requisições, você dá fôlego para o serviço que está sofrendo se recuperar (ex: reduzir carga de CPU).
Dica: Bulkhead
Combine o Circuit Breaker com o padrão Bulkhead. Enquanto o disjuntor para as chamadas, o Bulkhead isola os pools de threads para que a falha em um serviço de “E-mail” não consuma todas as threads do serviço de “Checkout”.
Checklist de Configuração do Disjuntor
Ao implementar o Circuit Breaker com Resilience4j ou similar, verifique estes parâmetros críticos:
- Failure Rate Threshold: Qual a porcentagem de erro aceitável antes de abrir o circuito? (Geralmente 50%).
- Wait Duration in Open State: Quanto tempo o sistema deve esperar antes de tentar o estado
HALF_OPEN? - Sliding Window Size: Quantas requisições serão analisadas para calcular a taxa de erro?
- Permitted Number of Calls in Half-Open: Quantos testes são suficientes para decidir fechar o circuito novamente?
- Fallback Method: Existe uma resposta padrão (cache ou erro amigável) para quando o serviço estiver fora do ar?