Careeroza
Circuit Breaker in Spring Boot
Annotate the Call
@Service
@RequiredArgsConstructor
@Slf4j
public class ProductCatalog {
private final ProductClient productClient;
private final ProductCache cache;
@CircuitBreaker(name = "productService", fallbackMethod = "cachedProduct")
public ProductDto getProduct(Long id) {
ProductDto product = productClient.getProduct(id);
cache.put(product);
return product;
}
// same parameters + a Throwable at the end, same return type
ProductDto cachedProduct(Long id, Throwable ex) {
log.warn("productService fallback for {}: {}", id, ex.getClass().getSimpleName());
return cache.find(id).orElseThrow(() -> new ServiceUnavailableException("product-service down"));
}
}Note: The annotations work through a Spring proxy, so calling getProduct from another method in the same class skips the circuit breaker. Call it from another bean.
Configure It
application.yml
application.yml
resilience4j:
circuitbreaker:
configs:
default:
sliding-window-type: COUNT_BASED # or TIME_BASED (last N seconds)
sliding-window-size: 10
minimum-number-of-calls: 5 # do not judge on 1-2 calls
failure-rate-threshold: 50 # %
slow-call-duration-threshold: 2s # slow calls count as bad too
slow-call-rate-threshold: 80
wait-duration-in-open-state: 10s
permitted-number-of-calls-in-half-open-state: 3
automatic-transition-from-open-to-half-open-enabled: true
register-health-indicator: true
instances:
productService:
base-config: default
ignore-exceptions: # business errors are not failures
- com.shopease.order.client.ProductNotFoundException
paymentService:
base-config: default
wait-duration-in-open-state: 30s
management:
health:
circuitbreakers:
enabled: true
endpoints:
web:
exposure:
include: health,circuitbreakers,circuitbreakereventsExample output
$ curl -s localhost:8082/actuator/circuitbreakers
{"circuitBreakers":{"productService":{"failureRate":"60.0%","slowCallRate":"0.0%",
"failureRateThreshold":"50.0%","slowCallRateThreshold":"80.0%","bufferedCalls":5,
"failedCalls":3,"slowCalls":0,"slowFailedCalls":0,"notPermittedCalls":4,"state":"OPEN"}}}
# order-service log
WARN c.s.order.ProductCatalog : productService fallback for 7: CallNotPermittedExceptionImportant Settings
| Property | Meaning | Typical |
|---|---|---|
sliding-window-size | How many recent calls to look at | 10–100 |
minimum-number-of-calls | No decision before this many calls | 5–20 |
failure-rate-threshold | % of failed calls that opens the circuit | 50 |
slow-call-duration-threshold | A call slower than this counts as slow | p99 latency × 2 |
wait-duration-in-open-state | How long to stay OPEN | 10–60 s |
permitted-number-of-calls-in-half-open-state | Trial calls | 3–10 |
record-exceptions / ignore-exceptions | Which errors count | Ignore 4xx business errors |