Как работает Circuit Breaker и какие у него состояния
Circuit Breaker имеет три состояния:
🟢 Junior Level
Circuit Breaker имеет три состояния:
- CLOSED (Закрыт) — всё нормально, вызовы проходят
- OPEN (Открыт) — сервис “сломан”, вызовы блокируются, сразу fallback
- HALF-OPEN (Полуоткрыт) — пробный вызов для проверки
Начало: CLOSED (вызовы проходят)
↓ слишком много ошибок
OPEN (блокируем вызовы 10 секунд)
↓ время вышло
HALF-OPEN (один пробный вызов)
↓ успех → CLOSED
↓ ошибка → OPEN (снова ждать)
🟡 Middle Level
Детали переходов
CLOSED → OPEN:
failureRate > threshold (например 50%)
ИЛИ slowCallRate > threshold (например > 50% медленных)
OPEN → HALF-OPEN:
waitDurationInOpenState elapsed (например 10 секунд)
HALF-OPEN → CLOSED:
permittedNumberOfCallsInHalfOpenState успешных вызовов
(например 3 успешных вызова)
HALF-OPEN → OPEN:
Любая ошибка в HALF-OPEN состоянии
Типичные ошибки
- Неправильный sliding window:
slidingWindowSize = 5 → слишком мало Одна ошибка = 20% failure rate Лучше: 10-100 вызовов
🔴 Senior Level
Internal Implementation
Metrics tracking:
// Ring buffer для хранения результатов вызовов
class SlidingWindow {
private final CircularArray measurements;
void record(CallResult result) {
measurements.add(result);
// Если minCalls никогда не набран — breaker НЕ откроется, даже если ВСЕ вызовы
// FAILED. Это важно: при малом трафике circuit breaker может не сработать.
if (measurements.size() >= minCalls) {
double failureRate = calculateFailureRate();
if (failureRate > threshold) {
stateTransition(CLOSED, OPEN);
}
}
}
}
Production Experience
Monitoring:
// Метрики для мониторинга
CircuitBreaker.Metrics metrics = circuitBreaker.getMetrics();
metrics.getFailureRate(); // % ошибок
metrics.getNumberOfBufferedCalls();
metrics.getNumberOfFailedCalls();
metrics.getState(); // CLOSED/OPEN/HALF-OPEN
Best Practices
// Эти паттерны НЕ альтернативы, а комплементарны: // Retry + Timeout + CircuitBreaker используются вместе.
✅ minimumNumberOfCalls = 10+ (статистически значимая выборка)
✅ failureRateThreshold = 50% (компромисс: не открываем от одной ошибки, но и не ждём пока всё упадёт)
✅ waitDurationInOpenState = 10-60s (достаточно чтобы зависимый сервис перезапустился, но не слишком долго)
✅ permittedCallsInHalfOpen = 3-5
❌ Слишком маленький sliding window
❌ Слишком короткий wait duration
❌ Без мониторинга метрик
🎯 Шпаргалка для интервью
Обязательно знать:
- Три состояния: CLOSED, OPEN, HALF-OPEN с чёткими правилами переходов
- CLOSED→OPEN: failure rate > threshold (50%), OPEN→HALF-OPEN: wait duration elapsed
- HALF-OPEN→CLOSED: N успешных вызовов, HALF-OPEN→OPEN: любая ошибка
- Sliding window (count-based или time-based) для отслеживания метрик
- minimumNumberOfCalls = 10+ для статистически значимой выборки
- При малом трафике circuit breaker может не сработать (не набран minCalls)
- Ring buffer для хранения результатов вызовов
Частые уточняющие вопросы:
- Что такое permittedNumberOfCallsInHalfOpen? Сколько пробных вызовов сделать в HALF-OPEN — если все успешны, вернуться в CLOSED.
- Почему minimumNumberOfCalls важен? Без него breaker откроется от 1-2 ошибок при малом трафике.
- Как мониторить CB? Метрики: failure rate, buffered calls, failed calls, текущее состояние.
- Count-based vs time-based window? Count-based = последние N вызовов, time-based = вызовы за T секунд.
Красные флаги (НЕ говорить):
- “Sliding window = 5 достаточно” — нет, одна ошибка = 20% failure rate
- “Wait duration = 1 секунда” — сервис не успеет перезапуститься
- “CB работает без метрик” — невозможно настроить без мониторинга
- “HALF-OPEN пропускает весь трафик” — нет, только permittedNumberOfCalls
Связанные темы:
- [[5. Что такое паттерн Circuit Breaker]]
- [[17. Как обеспечить отказоустойчивость микросервисов]]
- [[19. Что такое паттерн Retry и как его правильно использовать]]
- [[21. Как мониторить распределённую систему микросервисов]]
- [[20. Что такое exponential backoff]]