В распределённых системах сбои — не исключение, а норма. Сервис может зависнуть, база — отвечать медленно, внешний API — временно падать. Чтобы одна проблема не «уронила» всё приложение, используют паттерны отказоустойчивости. Два самых важных — Retry и Circuit Breaker.
1. Retry: повторная попытка запроса 🔁
Идея простая: если ошибка временная, запрос можно повторить.
Когда Retry полезен:
- кратковременные сетевые сбои
- временная недоступность сервиса
- ошибки 502/503/504
- таймауты из-за скачка нагрузки
Но Retry опасен, если применять его бездумно:
- можно усилить нагрузку на уже перегруженный сервис
- дублировать операции, если запрос не идемпотентен
- увеличить задержки для пользователя
Что важно в реализации:
- ограничивать число попыток
- использовать backoff — увеличивать паузу между повторами
- добавлять jitter — случайный разброс, чтобы тысячи клиентов не пошли одновременно
- ретраить только безопасные ошибки
Хорошая практика: exponential backoff + jitter.
2. Circuit Breaker: автоматический предохранитель ⚡
Этот паттерн нужен, когда сервис начинает массово ошибаться. Вместо бесконечных попыток система временно прекращает слать запросы в проблемный сервис.
Обычно у Circuit Breaker есть 3 состояния:
- Closed — всё работает, запросы идут как обычно
- Open — ошибок слишком много, запросы блокируются на время
- Half-Open — система осторожно проверяет, восстановился ли сервис
Зачем это нужно:
- защищает систему от каскадных отказов
- снижает нагрузку на проблемный сервис
- ускоряет ответ пользователю, если заранее ясно, что сервис недоступен
- помогает быстрее восстановиться всей системе
Пример:
Если платёжный шлюз начал отдавать таймауты, без Circuit Breaker ваше приложение будет ждать каждый запрос и забивать пул потоков. С Circuit Breaker можно быстро вернуть fallback: «Платёж временно недоступен».
Retry + Circuit Breaker: как использовать вместе 🧩
Эти паттерны не конкурируют, а дополняют друг друга.
Рабочая схема:
- сначала делаем 1–3 разумных retry
- если ошибки повторяются массово — срабатывает Circuit Breaker
- пользователю отдаётся fallback или понятная ошибка
Важно:
- Retry не должен быть слишком агрессивным
- Circuit Breaker не должен открываться из-за единичных сбоев
- оба паттерна нужно настраивать по метрикам, а не «на глаз»
Когда применять 📌
- есть внешние API
- микросервисная архитектура
- высокая нагрузка
- критичны доступность и стабильность
- нужно избежать каскадных сбоев
Итог
Retry помогает пережить временные сбои.
Circuit Breaker не даёт сбоям распространяться по системе.
Вместе они делают архитектуру устойчивее, а поведение приложения — предсказуемее даже в аварийных сценариях. 🚀
За полезными источниками — посмотрите подборку каналов про IT 👀