Вопрос 6 · Раздел 17

Как работает Circuit Breaker и какие у него состояния

Circuit Breaker имеет три состояния:

Версии по языкам: English Russian Ukrainian

🟢 Junior Level

Circuit Breaker имеет три состояния:

  1. CLOSED (Закрыт) — всё нормально, вызовы проходят
  2. OPEN (Открыт) — сервис “сломан”, вызовы блокируются, сразу fallback
  3. 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 состоянии

Типичные ошибки

  1. Неправильный 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]]