Ретраи (retries) в проектировании систем — механизм авто-повторения неудачных операций при временных сбоях (сетевых ошибках, перегрузке сервисов и тд)
В распределенных системах временные сбои— норма
Вызов "повторить при ошибке" может усугубить проблему
Виды ошибок
Не все ошибки равны: ретраить можно только временные сбои.
Постоянные ошибки повторять бесполезно и вредно для ретраев
🔼 Повторяемые ошибки
Временные сбои, которые могут исчезнуть при повторной попытке
Типичные кейсы повторяемых ошибок:
◾️Сетевые сбои
Таймауты TCP, Connection Reset
➡️ проблемы балансировщика, кратковременная недоступность сети
◾️Ограничения ресурсов
HTTP 429 (Too Many Requests)
➡️ превышение лимитов API (Rate Limiting)
пример: пльзователь массово экспортирует данные → API временно ограничивает запросы
◾️Ошибки серверов
HTTP 5xx (503, 504)
➡️ перегрузка сервера, деградация БД
пример: (HTTP 503) сервис перегружен в час пик
◾️Конфликты данных
Дедлоки БД, оптимистичные блокировки
➡️ конкурентные транзакции
пример: деадлоки БД - два клиента одновременно редактируют один заказ
⤵️ Постоянные ошибки
🔹HTTP 400 (Bad Request)
Клиент отправил невалидные данные (например, буквы в поле "Цена"). Повторы бесполезны
🔹HTTP 404 (Not Found)
Ресурс удален (например, несуществующий ID товара). Повторы создают нагрузку
🔹HTTP 403 (Forbidden)
Постоянное отсутствие прав (например, просмотр чужих заказов)
Стратегии повторов
🤩Экспоненциальная задержка (Exponential Backoff)
Растущая задержка: 1с → 2с → 4с → 8с
Для снижение нагрузки на сбойный ресурс, дает ему время на восстановление
✨пример: пользователь оплачивает заказ → платежный шлюз временно недоступен → система повторяет через 0.5с, 1с, 2с → 95% платежей проходят со 2-3 попытки
🤩Джиттер (Jitter)
Когда к задержке добавляется случайное значение, чтобы 1000 запросов не повторились одновременно
Фактическая задержка = Базовая задержка + random(0, 30% от задержки)
Для предотвращение синхронизации запросов
✨пример: 10 000 корзин ожидают оплаты
Без джиттера: повтор всех 10к запросов одновременно → Коллапс платежной системы
С джиттером: запросы распределяются равномерно
🤩Комбинированные подходы
a) Retry-After + Backoff
Использование заголовка HTTP Retry-After для точного определения задержки
HTTP/1.1 429 Too Many Requests
Retry-After: 15 ← Ждать ровно 15 секунд✨ когда использовать: при интеграции с внешними API
b) Адаптивные ретраи
Динамический расчет задержки на основе:
- истории ответов сервиса
- текущей нагрузки
- SLA системы и тд
✨пример: система логирования увеличивает задержку с 1с до 10с при 1000 ошибок/мин.
🤩Ограничение попыток
Максимальное число ретраев (напр. 3-5).
Это предотвращает бесконечные циклы.
После исчерпания попыток— фиксируется ошибка
✨например:
- асинхронная обработка (отправка в очередь)
- уведомление мониторинга
Circuit Breaker ("предохранитель" системы)
Это "автомат", который временно блокирует вызовы сбойного сервиса
🌸 принцип: после N ошибок за период T, все последующие вызовы завершаются ошибкой без реального вызова ресурса.
Периодически проверяет "полуоткрытое" состояние.
💡 Следует определить пороги срабатывания (N, T), время восстановления
Связать с SLA и поведением системы при отказе.
Состояния брейкера:
🔵Closed: вызовы проходят
Система работает нормально
🔵Open: вызовы блокируются (ошибка без реального запроса)
После 5 ошибок за 1 мин
🔵Half-Open: Пропускает часть трафика для проверки восстановления
➡️кейс: сервис отправки SMS падает → Circuit Breaker блокирует вызовы на 2 мин → предотвращает:
- потерю денег за SMS
- перегрузку очереди сообщений
- каскадные сбои
📎 Материалы
1. Хороший ретрай, плохой ретрай, или История одного падения
2. Отложенные ретраи силами RabbitMQ
3. Как работать над перфомансом веб-приложения: опыт Авто.ру|
4. Лучшие практики создания отказоустойчивых систем
🔹 Производительность API: краткий обзор способов
📚 Паттерны проектирования API - Джей Гивакс (Часть IV. Безопасность)
#проектирование #api
➿➿➿➿➿➿➿➿
🧑🎓 Больше полезного в базе знаний по системному анализу