Повторные запросы: экспоненциальная задержка и jitter
Расчёт задержек exponential backoff с разбросом (jitter): минимум, среднее и максимум по попыткам, общее время до отказа и готовый код.
Данные обрабатываются в браузере и никуда не отправляются
Ввод
Результат
Здесь появится результат
Введите данные слева - результат появится сразу
Как пользоваться
Введите начальную задержку, множитель, максимальную задержку и число повторов, выберите способ разброса (jitter) - таблица покажет для каждого повтора минимальную, среднюю и максимальную задержку, а сверху - суммарное время до окончательного отказа. Внизу - готовый код для JavaScript и Python с вашими параметрами. Это помогает подобрать настройки повторов так, чтобы клиент не ждал слишком долго и не перегружал упавший сервис.
Типичные настройки: начало 1 секунда, множитель 2, потолок 30-60 секунд, 5-8 повторов и полный разброс. Повторять можно только идемпотентные запросы (GET, PUT, DELETE) либо запросы с ключом идемпотентности.
Частые ошибки
Вот что чаще всего делают неправильно с повторными запросами:
Повторы без разброса (jitter)
Если все клиенты упали одновременно, без разброса они повторят запрос в одну и ту же секунду, снова перегрузят сервис и снова упадут. Это «гроза повторов» (thundering herd). Случайный разброс размазывает нагрузку по времени.
Повтор неидемпотентных запросов
Повтор POST после таймаута может создать дубль: платёж или заказ. Повторяйте только идемпотентные запросы либо отправляйте ключ идемпотентности (Idempotency-Key), чтобы сервер отличал повтор от нового запроса.
Повторы любых ошибок
Ошибки 400, 401, 403, 404 и 422 не исправятся от повторов. Повторяйте сетевые ошибки, 408, 429 и 5xx (502, 503, 504), учитывая заголовок Retry-After. Ошибка клиента должна возвращаться сразу, а не после минут ожидания.
Нет потолка задержки
Без максимальной задержки при начальной паузе в 1 секунду и множителе 2 одиннадцатый повтор ждёт около 17 минут, а двадцатый - больше шести суток. Ограничивайте и задержку, и число повторов, и общее время.
Игнорирование Retry-After
Если сервер вернул 429 или 503 с Retry-After, он сам подсказывает, когда можно повторить. Расчётная задержка меньше этого значения только вредит: используйте большее из двух.
Повторы на всех уровнях сразу
Если клиент, шлюз и сервис повторяют по три раза, один сбой превращается в 27 запросов к базе. Повторы нужны на одном-двух уровнях, плюс предохранитель (circuit breaker) и общий бюджет повторов.
Частые вопросы
Отправляются ли мои данные на сервер?
Нет - 100%. Сайт целиком статический, у него нет серверной части. Расчёты выполняются в вашем браузере, введённые числа никуда не отправляются.
Что такое экспоненциальная задержка (exponential backoff)?
Это стратегия повторов, при которой пауза между попытками растёт по степенному закону: 1 с, 2 с, 4 с, 8 с... Так сервису дают время восстановиться, а клиент не забрасывает его запросами. Рост ограничивают потолком.
Чем отличаются полный, равный и decorrelated jitter?
Полный: задержка случайна от нуля до расчётного значения (лучше всего размазывает нагрузку). Равный: половина расчётной плюс случайная половина (сохраняет минимальную паузу). Decorrelated: каждая следующая зависит от предыдущей случайной, растёт быстрее и разбросаннее. Обзор подходов - в блоге AWS Architecture.
Какие запросы можно повторять?
Идемпотентные: GET, HEAD, PUT, DELETE, OPTIONS - повтор не меняет результат. POST и PATCH - только с ключом идемпотентности. Ошибки, которые стоит повторять: таймауты, сбои соединения, 408, 429, 500, 502, 503, 504 (последние - осторожно, операция могла выполниться).
Сколько повторов делать?
Обычно 3-8: больше смысла нет, потому что суммарное ожидание становится слишком большим для пользователя. Для фоновых задач и очередей повторов можно делать больше, с большим потолком задержки и сохранением состояния.
Что такое circuit breaker и зачем он при повторах?
Это предохранитель: после серии неудач клиент на время перестаёт отправлять запросы к сервису, не тратя ресурсы и не добивая его. Через паузу он пробует один запрос и, если всё хорошо, возобновляет работу. Он дополняет backoff, а не заменяет его.
Как backoff связан с таймаутом?
Таймаут ограничивает ожидание одной попытки, backoff - паузу между попытками. Общее время до отказа - сумма пауз плюс таймауты всех попыток. Укажите таймаут попытки, чтобы увидеть реальное время, которое будет ждать клиент.
Откуда взять Retry-After и как его учесть?
Заголовок присылает сервер вместе с 429 или 503: число секунд или дата. Клиент должен ждать не меньше этого значения. Если задержка по расчёту больше - берите её, если меньше - Retry-After.
Похожие инструменты
Курс «Проектирование API и интеграций»
Глубокое погружение в REST, gRPC, SOAP, проектирование баз данных и брокеры сообщений (Kafka, RabbitMQ). Делегирование рутины нейросетям (ИИ). Перестанете бояться технических собеседований и начнете говорить с разработчиками на одном языке. Курс собран так, чтобы пробить зарплатный потолок и вырасти в грейде - ученики тому подтверждение.
Перейти к курсу на Stepik