← Назад к блогу
Системная архитектура 27.06.2024·4 мин чтения

Circuit Breaker, Retry, Timeout: базовый набор устойчивости

Три механизма, которые защищают сервис от каскадных отказов: где ставить, как настраивать и какие ошибки избегать.

Большинство падений в распределённых системах — это не «один большой сбой», а цепочка мелких деградаций.

Базовая защита строится на трёх механизмах: timeout, retry, circuit breaker.

Проще говоря

Три механизма, которые защищают сервис от каскадных отказов: где ставить, как настраивать и какие ошибки избегать. Ниже — что именно делать на практике и где чаще всего ошибаются.

1) Timeout — всегда первым

Без timeout любой внешний вызов может «подвесить» воркер/поток.

Правила:

  • отдельный timeout на connect и read,
  • timeout короче SLA endpoint,
  • явная отмена/прерывание запроса.

2) Retry — только на безопасных ошибках

Retry полезен при временных сбоях, но опасен без ограничений.

Нужно:

  • ограничить число попыток,
  • использовать exponential backoff + jitter,
  • ретраить только retryable errors,
  • учитывать идемпотентность операции.

3) Circuit Breaker — защита от каскада

Когда зависимый сервис деградирует, breaker временно «открывается» и прекращает новые тяжёлые попытки.

Состояния:

  • closed (норма),
  • open (отсекаем вызовы),
  • half-open (пробуем восстановление).

4) Порядок применения

Обычно лучше так:

  1. timeout,
  2. retry (ограниченный),
  3. circuit breaker,
  4. резервный сценарий (если применимо).

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

  1. Бесконечные ретраи.
  2. Ретраи на 4xx/валидации.
  3. Один глобальный timeout «на всё».
  4. Breaker без метрик и алертов.

6) Метрики устойчивости

  • доля timeout-ов,
  • retry rate и retry success rate,
  • breaker open rate,
  • latency внешних зависимостей,
  • резервный сценарий usage.

Короткая история из команды

При деградации внешнего сервиса система сначала терпела, потом падала каскадом. После нормальной связки timeout + ограниченный retry + breaker инциденты перестали распространяться на весь контур.

Вывод

Эти три механизма должны быть не «опцией в библиотеке», а частью архитектурного стандарта.

Когда они настроены осознанно, система перестаёт падать каскадом из-за одной внешней проблемы.

Практический сценарий внедрения

Если внедрять подход поэтапно, лучше идти от самого болезненного потока: выбрать один критичный user-journey, зафиксировать текущие метрики и применить изменения только на этом участке. Такой подход снижает риск и даёт быстрый доказуемый эффект для команды.

Метрики, которые важно отслеживать

  • p95/p99 latency для ключевых операций,
  • error rate и доля retry/резервный сценарий,
  • время восстановления после сбоев,
  • стоимость обработки запроса/события,
  • доля регрессий после релизов.

Без метрик даже сильные архитектурные решения быстро превращаются в набор гипотез.

Что обычно идёт не так

  1. Команда пытается внедрить всё сразу вместо поэтапного поэтапный запуск.
  2. Нет владельца архитектурного решения и контроль расслаивается.
  3. Решение есть в документации, но не встроено в CI/CD и runbook.
  4. После внедрения нет регулярного review, и качество снова деградирует.

Пошаговый план на 30 дней

  • Неделя 1: базовый уровень, ограничения, целевые KPI.
  • Неделя 2: внедрение в одном потоке + алерты.
  • Неделя 3: стабилизация, фиксы edge-cases.
  • Неделя 4: масштабирование на соседние модули и обновление стандартов команды.

Термины простыми словами

  • SLA/SLI/SLO — договорённость о качестве сервиса: что измеряем, какой целевой уровень и какие последствия при деградации.
  • Idempotency — свойство операции давать тот же корректный результат при повторе одного и того же запроса.
  • Circuit Breaker — защитный механизм, временно останавливающий вызовы в деградирующую зависимость, чтобы избежать каскадного отказа.
  • Политика повторов — правила повторных попыток (когда, сколько раз и с каким backoff), чтобы не усилить сбой.

Этот блок нужен, чтобы статью можно было читать без предварительного контекста по всем терминам.

Как применять это в живом проекте

Обычно команда упирается не в идею решения, а в внедрение: кто владелец, где проверить эффект, как не сломать соседние модули. Поэтому лучше запускать изменения через один критичный поток, где есть понятная боль и измеримый результат.

Хорошая последовательность: сначала фиксируем baseline, затем внедряем минимально жизнеспособную версию решения, после чего смотрим на метрики 1–2 недели. Если эффект подтверждается, масштабируем на соседние сценарии. Если нет — откатываем без драм и пересобираем гипотезу.