Todo mundo já ouviu falar que 'circuit breaker é essencial para microsserviços'. Mas será que a implementação com fallback é tão simples quanto parece? A verdade é que muitos desenvolvedores esquecem de configurar o fallback corretamente e acabam com um circuito que não protege nada. Neste guia, você vai aprender o passo a passo para implementar um circuit breaker fallback funcional, usando Resilience4j como biblioteca de referência. O resultado esperado é um serviço que, ao detectar falhas consecutivas, para de chamar o recurso problemático e retorna uma resposta alternativa, mantendo a aplicação disponível.
Antes de começar, você precisa de um projeto Java com Spring Boot (ou outro framework compatível), a dependência do Resilience4j configurada e um serviço externo que possa falhar (real ou simulado).
Passo 1: Adicione a dependência do Resilience4j
O primeiro passo é incluir a biblioteca no seu projeto. Se estiver usando Maven, adicione ao pom.xml:
<dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-spring-boot2</artifactId> <version>1.7.0</version> </dependency>
Para Gradle, use implementation 'io.github.resilience4j:resilience4j-spring-boot2:1.7.0'. Essa dependência já traz o suporte a anotações e configuração via application.yml.
Dica: Verifique a versão mais recente no repositório oficial. Usar uma versão desatualizada pode causar incompatibilidade com o Spring Boot.
Erro comum: Esquecer de adicionar a dependência do AOP (spring-boot-starter-aop). Sem ela, as anotações @CircuitBreaker não funcionam.
Passo 2: Configure o circuit breaker no application.yml
Com a dependência pronta, defina as propriedades do circuit breaker. Exemplo:
resilience4j.circuitbreaker: instances: meuServico: registerHealthIndicator: true slidingWindowSize: 10 minimumNumberOfCalls: 5 permittedNumberOfCallsInHalfOpenState: 3 waitDurationInOpenState: 10s failureRateThreshold: 50
Esses valores controlam quando o circuito abre. slidingWindowSize define quantas chamadas são monitoradas; failureRateThreshold é o percentual de falhas que dispara a abertura.
Dica: Comece com valores conservadores e ajuste conforme o comportamento do seu sistema. Um threshold de 50% é comum, mas sistemas críticos podem usar 30%.
Erro comum: Não configurar o minimumNumberOfCalls. Se deixar o padrão, o circuito pode abrir com pouquíssimas chamadas, gerando falsos positivos.
Passo 3: Anote o método com @CircuitBreaker e defina o fallback
Agora, no seu serviço, anote o método que faz a chamada externa:
@CircuitBreaker(name = "meuServico", fallbackMethod = "fallbackMeuServico") public String chamarServicoExterno() { return restTemplate.getForObject("http://externo/api", String.class); }
public String fallbackMeuServico(Throwable t) { return "Resposta padrão do fallback"; }
O método de fallback deve ter a mesma assinatura do método original, acrescido do parâmetro Throwable (ou a exceção específica). Ele será chamado quando o circuito estiver aberto ou quando ocorrer uma exceção.
Dica: O fallback pode retornar um valor em cache, uma mensagem amigável ou até mesmo chamar um serviço alternativo. A escolha depende do contexto.
Erro comum: Declarar o fallback com assinatura diferente. Isso faz o Resilience4j não encontrar o método e lançar uma exceção em tempo de execução.
Passo 4: Teste o circuit breaker e o fallback
Para validar, simule falhas no serviço externo. Você pode usar um mock que lança exceções após algumas chamadas. Com o circuito configurado, após o número mínimo de chamadas e a taxa de falha excedida, o circuito abre. As chamadas seguintes devem executar o fallback imediatamente, sem tentar o serviço externo.
Dica: Use ferramentas como WireMock ou Mockito para simular falhas de forma controlada. Monitore as métricas do Resilience4j (via Actuator) para ver o estado do circuito.
Erro comum: Não testar o estado half-open. Após o tempo de espera, o circuito permite algumas chamadas para verificar se o serviço se recuperou. Se não testar, você pode ter surpresas em produção.
Passo 5: Monitore e ajuste
Implementar é só o começo. Monitore as métricas: número de chamadas, taxa de falha, estado do circuito. O Resilience4j expõe endpoints do Actuator, como /actuator/circuitbreakers. Ajuste os parâmetros conforme necessário.
Dica: Configure alertas para quando o circuito abrir. Isso indica que algo está errado com o serviço externo e você pode agir proativamente.
Erro comum: Ignorar os logs. O Resilience4j registra transições de estado. Acompanhe para entender o comportamento.
Checklist rápido
- Dependência do Resilience4j adicionada (incluindo AOP)
- Configuração do circuit breaker no application.yml
- Método anotado com @CircuitBreaker e fallbackMethod
- Fallback com assinatura correta
- Testes de falha e recuperação realizados
- Monitoramento via Actuator configurado
FAQ
O que é circuit breaker fallback?
É um padrão de resiliência em que, quando o circuit breaker está aberto (devido a falhas repetidas), uma lógica alternativa (fallback) é executada em vez de chamar o serviço problemático. Isso evita falhas em cascata e melhora a experiência do usuário.
Qual a diferença entre fallback e retry?
Retry tenta novamente a mesma operação, enquanto fallback executa uma ação alternativa. Retry é útil para falhas transitórias; fallback é para quando o serviço está indisponível. Ambos podem ser combinados.
O fallback é executado mesmo se o circuito estiver fechado?
Sim, se ocorrer uma exceção durante a chamada, o fallback é acionado independentemente do estado do circuito. O Resilience4j permite configurar quais exceções disparam o fallback.
Posso ter múltiplos fallbacks para o mesmo método?
Não diretamente. Você pode definir um único método de fallback, mas dentro dele pode tratar diferentes exceções e retornar respostas distintas. Para múltiplos, é necessário usar anotações separadas ou lógica condicional.
Como testar o circuit breaker em ambiente local?
Use mocks para simular falhas. Ferramentas como WireMock ou Mockito ajudam a criar cenários controlados. Verifique as métricas via Actuator para confirmar a abertura do circuito.
O que acontece se o fallback também falhar?
Se o fallback lançar uma exceção, ela será propagada. É importante garantir que o fallback seja robusto e não dependa de recursos externos que possam falhar. Mantenha-o simples e confiável.