In a monolithic system, a component failure throws an exception. In a distributed microservice architecture, a failure in a downstream service can exhaust connection pools, tie up worker threads, and trigger catastrophic cascading outages across the entire network.
The Circuit Breaker Pattern is the primary defense against distributed cascading failures.
1. How a Circuit Breaker Works
A circuit breaker monitors calls to remote services and transitions through three operational states:
- CLOSED: Normal operation. Requests pass through to downstream services.
- OPEN: If the failure rate crosses a defined threshold (e.g. 50% failures over 10 calls), the breaker trips OPEN. All subsequent requests fail immediately without attempting network calls, shielding the struggling downstream service.
- HALF-OPEN: After a configured sleep window, the breaker permits a limited number of trial requests. If they succeed, it resets to CLOSED; if they fail, it trips back to OPEN.
2. Implementing Resilience4j in Spring Boot
@Service
public class PaymentGatewayClient {
@CircuitBreaker(name = "paymentService", fallbackMethod = "fallbackPaymentProcessing")
@Retry(name = "paymentService")
public PaymentResponse processTransaction(PaymentRequest request) {
return restTemplate.postForObject("/api/v1/charge", request, PaymentResponse.class);
}
// Graceful fallback executed when circuit is OPEN or call fails
public PaymentResponse fallbackPaymentProcessing(PaymentRequest request, Throwable t) {
log.warn("Downstream payment service unavailable. Queuing offline transaction: {}", t.getMessage());
return new PaymentResponse("QUEUED_FOR_OFFLINE_SETTLEMENT", request.getTransactionId());
}
}
```