Что такое паттерн 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
Как работает
// Резилиент4j (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. Как организовать коммуникацию между микросервисами]]