Circuit Breaker на собеседовании системного аналитика

Готовься к собесу аналитика как в Duolingo
10 минут в день — SQL, Python, A/B, метрики. 1700+ вопросов в Telegram
Открыть Карьерник в Telegram

Карьерник — Duolingo для аналитиков: 10 минут в день тренируй SQL, Python, A/B, статистику, метрики и ещё 3 темы собеса. 1500+ вопросов в Telegram-боте. Бесплатно.

Зачем спрашивают на собесе SA

Resilience patterns — must-know для микросервисной архитектуры. На собесе SA: «как работает circuit breaker», «отличие от retry», «зачем bulkhead».

Идея circuit breaker

Сервис A зависит от сервиса B. B падает / медленный — A продолжает делать запросы и тоже встаёт (cascade failure).

Circuit breaker — автоматический «выключатель» вызовов B, если он плохо работает. После cooldown — проверка, если работает, возвращаем normal flow.

Состояния: closed / open / half-open

Closed. Нормальное состояние. Запросы проходят. Failures считаются.

Open. После N failures за период — переключение в open. Запросы немедленно fail без обращения к downstream. Защита downstream от добивания + быстрая ошибка для caller.

Half-open. После cooldown timer — пропускаем 1-N тестовых запросов. Если успешные → closed. Если fail → open снова.

        request fails
closed ──────────────→ open
   ↑                    │
   │ test passes        │ cooldown timer
   │                    ↓
   └────── half-open ←──┘
        (тестовый запрос)

Retries и timeouts

Circuit breaker — не единственный pattern. Часто используется вместе с:

Timeout. Не ждать ответа дольше N секунд. Без timeout — просто зависание.

Retry с exponential backoff. Повторить через 1s, 2s, 4s, 8s. Не сразу — может усугубить нагрузку.

Retry only for idempotent. GET, PUT — да. POST — нет (может создать дубль).

Jitter. Добавить randomness к backoff — иначе все клиенты retry в один момент (thundering herd).

Готовься к собесу аналитика как в Duolingo
10 минут в день — SQL, Python, A/B, метрики. 1700+ вопросов в Telegram
Открыть Карьерник в Telegram

Bulkhead pattern

Изолировать ресурсы между вызовами разных downstream'ов.

Без bulkhead. Один thread pool на все вызовы. Один медленный downstream забивает pool — остальные стоят.

С bulkhead. Отдельный thread pool / connection pool для каждого downstream. Деградация одного не убивает остальные.

Service A:
  ├─ Pool for service B (10 threads)
  ├─ Pool for service C (10 threads)
  └─ Pool for service D (10 threads)

Если B встал — A продолжает обслуживать запросы к C и D.

Реализация

Hystrix (Netflix, deprecated). Стандарт раньше.

Resilience4j (Java). Современный.

Polly (.NET). Resilience policies.

istio / Envoy — на уровне sidecar.

Custom. Простой circuit breaker — пара десятков строк Python / Go.

class CircuitBreaker:
    def __init__(self, threshold=5, timeout=30):
        self.failures = 0
        self.threshold = threshold
        self.last_failure = None
        self.timeout = timeout

    def call(self, fn):
        if self.is_open():
            raise CircuitOpenError
        try:
            result = fn()
            self.failures = 0
            return result
        except Exception:
            self.failures += 1
            self.last_failure = time.time()
            raise

Частые ошибки

Высокий threshold. «10 failures за 5 минут» — слишком terpимо, downstream добивается. Обычно 3-5 за минуту.

Slow timeout. 60-секундный timeout на user-facing — катастрофа. 500ms-3s стандарт.

Ретрай non-idempotent. Дубли, money lost.

Без jitter. Thundering herd при cooldown.

Полагаться только на CB. Comprehensive resilience — timeouts + retries + CB + bulkhead.

Связанные темы

FAQ

Где SA участвует в circuit breaker?

В нефункциональных требованиях: «вызовы к Service B должны иметь timeout 2s, retry 3, circuit breaker threshold 5».

Это официальная информация?

Нет. Статья основана на работах Martin Fowler, Michael Nygard «Release It!», документации Istio.


Тренируйте системный анализ — откройте тренажёр с 1500+ вопросами для собесов.