Що таке патерн Circuit Breaker
Cascade failure (ланцюговий збій): сервіс A чекає сервіс B, сервіс C чекає A — усі потоки зависають, і вся система падає.
🟢 Junior Level
Circuit Breaker (запобіжник) — патерн, який захищає сервіс від виклику сервісу, що не працює.
Аналогія з життя: електричний запобіжник вимикає струм при перевантаженні, щоб не згоріла проводка.
Три стани:
- CLOSED — звичайний режим, виклики проходять
- OPEN — виклики блокуються (сервіс “зламаний”)
- HALF-OPEN — пробний виклик (перевірка, чи полагоджений сервіс)
Сервіс A → Сервіс B (працює)
↓ (почав гальмувати)
Circuit Breaker → OPEN (блокує виклики)
↓ (почекали, перевірка)
Circuit Breaker → HALF-OPEN → один виклик для перевірки
↓ (успіх!)
Circuit Breaker → CLOSED (знову працює)
🟡 Middle Level
Як працює
// Resilience4j
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.failureRateThreshold(50) // 50% — компроміс: не відкриваємо від однієї випадкової помилки.
// slidingWindowSize=10, minimumNumberOfCalls=5: потрібно мінімум 5 викликів,
// і якщо 50%+ з них FAILED — breaker відкривається.
.waitDurationInOpenState(Duration.ofSeconds(10)) // чекати 10 сек
.slidingWindowSize(10) // останні 10 викликів
.build();
CircuitBreaker circuitBreaker = CircuitBreaker.of("backend", config);
// Використання
Supplier<String> decorated = CircuitBreaker
.decorateSupplier(circuitBreaker, () -> backendService.call());
Try.of(decorated)
.onSuccess(result -> process(result))
.onFailure(error -> fallback());
Коли використовувати
✅ Circuit Breaker потрібен коли:
- Зовнішній сервіс може бути недоступний
- Мережеві проблеми (timeout, connection refused)
- Потрібно захистити свій сервіс від cascade failure
Cascade failure (ланцюговий збій): сервіс A чекає сервіс B, сервіс C чекає A — усі потоки зависають, і вся система падає.
❌ Circuit Breaker не потрібен коли:
- Виклик завжди швидкий і надійний
- Внутрішні виклики в одному процесі
Типові помилки
- Занадто агресивний threshold:
failureRateThreshold = 10% → OPEN після 1 помилки з 10 Занадто багато false positives
🔴 Senior Level
Internal Implementation
State transitions:
CLOSED → OPEN: failure rate > threshold
OPEN → HALF-OPEN: wait duration elapsed
HALF-OPEN → CLOSED: success call
HALF-OPEN → OPEN: failure call
Sliding window:
COUNT-based: останні N викликів
TIME-based: виклики за останні T секунд
Resilience4j підтримує обидва типи
Архітектурні Trade-offs
| Підхід | Плюси | Мінуси |
|---|---|---|
| Circuit Breaker | Швидкий fallback, бо не тратить час на очікування timeout від сервісу, що не працює — одразу повертає заглушку. | Складне налаштування |
| Retry | Пробує знову | Може погіршити проблему |
| Timeout | Захист від зависання | Не захищає від помилок |
Production Experience
Spring Boot + Resilience4j:
@CircuitBreaker(name = "backend", fallbackMethod = "fallback")
@Retry(name = "backend")
@TimeLimiter(name = "backend")
public CompletableFuture<String> callBackend(String input) {
return backendService.callAsync(input);
}
public CompletableFuture<String> fallback(String input, RuntimeException ex) {
return CompletableFuture.completedFuture("fallback: " + input);
}
Configuration:
resilience4j:
circuitbreaker:
instances:
backend:
slidingWindowSize: 10
failureRateThreshold: 50
waitDurationInOpenState: 10s
permittedNumberOfCallsInHalfOpenState: 3
minimumNumberOfCalls: 5
Best Practices
✅ Налаштовуйте threshold за метриками
✅ Використовуйте fallback для graceful degradation
✅ Моніторьте стан Circuit Breaker
✅ Комбінуйте з Retry і Timeout
❌ Не використовуйте занадто низький threshold
❌ Не ігноруйте HALF-OPEN стан
❌ Не використовуйте без fallback
🎯 Шпаргалка для співбесіди
Обов’язково знати:
- Circuit Breaker захищає від cascade failure, блокуючи виклики до сервісу, що не працює
- Три стани: CLOSED (норма), OPEN (блокування), HALF-OPEN (перевірка)
- Перехід CLOSED→OPEN при перевищенні failure rate threshold (зазвичай 50%)
- OPEN→HALF-OPEN після wait duration (10-60 сек), HALF-OPEN→CLOSED при успіху
- Sliding window (10-100 викликів) для статистично значущої вибірки
- Завжди комбінуйте з fallback для graceful degradation
- Resilience4j — стандартна бібліотека для Java/Spring
Часті уточнюючі питання:
- Чому 50% threshold? Компроміс: не відкриваємо від однієї випадкової помилки, але і не чекаємо поки все впаде.
- Навіщо HALF-OPEN? Перевірити, чи полагоджений сервіс, перш ніж відновити повний трафік.
- Чим Circuit Breaker кращий простого timeout? Timeout захищає від зависання, але не від cascade failure — CB одразу повертає fallback, не витрачаючи час.
- Як рахувати failure rate? Sliding window: останні N викликів або виклики за T секунд.
Червоні прапорці (НЕ говорити):
- “Circuit Breaker = Retry” — ні, CB блокує, Retry пробує знову
- “Threshold 10% — надійність” — ні, буде багато false positives
- “CB не потрібен для внутрішніх сервісів” — cascade failure можливий всюди
- “HALF-OPEN можна пропустити” — без нього не дізнатись, чи полагоджений сервіс
Пов’язані теми:
- [[6. Як працює Circuit Breaker і які у нього стани]]
- [[17. Як забезпечити відмовостійкість мікросервісів]]
- [[18. Що таке патерн Bulkhead]]
- [[19. Що таке патерн Retry і як його правильно використовувати]]
- [[15. Як організувати комунікацію між мікросервісами]]