Получить доступ

Как правильно настраивать таймауты и повторы запросов?

MiddleПерегрузка, лимиты и ретраи
Ещё спрашивают так:
  • Что такое экспоненциальная отсрочка с джиттером?
  • Что такое retry budget?
  • Как передавать дедлайн по цепочке вызовов?
Коротко

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

  • Повторы на каждом уровне цепочки перемножаются: 3 уровня × 3 попытки = 27 запросов вниз
  • Retry budget: повторы не больше ~10% от обычных запросов
  • Дедлайн передаётся вниз: нижние сервисы не работают дольше, чем ждёт верхний

А ещё Не повторять 4xx (кроме 429), повторять таймауты и 5xx осторожно

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Таймауты. Без таймаута зависший ответ навсегда занимает поток, соединение и память — так медленная зависимость останавливает весь сервис. Нужны раздельно: на установку соединения (короткий) и на ответ. Значение — от измеренного распределения задержек зависимости (около p99.9 с запасом), а не круглое «30 секунд». И таймаут на всю операцию целиком, а не только на одну попытку.

Повторы спасают от кратковременных сбоев (перезапуск экземпляра, потеря пакета), но опасны:

  • повторять можно только идемпотентные операции — или делать их идемпотентными ключом идемпотентности;
  • что повторять: таймауты, обрыв соединения, 502/503/504, 429 (с учётом Retry-After); не повторять 400, 401, 403, 404, 409;
  • экспоненциальная отсрочка — пауза 100 мс, 200, 400… с потолком;
  • джиттер — случайная пауза в пределах отсрочки (full jitter: random(0, base·2^n)). Без него тысячи клиентов после сбоя повторяют синхронно волнами и снова кладут сервис;
  • ограничение числа попыток — 2–3.

Шторм повторов. Если каждый из трёх уровней цепочки делает 3 попытки, нижний сервис при сбое получает до 27 запросов на один пользовательский. Повторы надо делать на одном уровне (обычно ближе к краю) или ограничивать бюджетом: повторов не больше 10% от успешных запросов за окно (gRPC retry throttling, Finagle). Когда зависимость лежит, бюджет кончается, и повторы прекращаются сами. Circuit breaker решает ту же задачу резче — перестаёт звать зависимость на время.

Дедлайны. Вместо независимых таймаутов на каждом уровне — абсолютный срок, передаваемый вниз (gRPC deadline, заголовок). Нижний сервис видит, что времени осталось 50 мс, и не начинает работу на 200 мс; верхний не ждёт дольше своего срока. Иначе нижние продолжают считать то, что верхний уже выбросил.

Hedging — разновидность повтора для хвостов: копия запроса после p95 без ожидания ошибки, только для чтения.

Пример

import random, time

def call_with_retry(fn, attempts=3, base=0.1, cap=2.0, deadline=None):
    for n in range(attempts):
        try:
            return fn(timeout=min(1.0, deadline - time.monotonic()) if deadline else 1.0)
        except (TimeoutError, ConnectionError, ServiceUnavailable):
            if n == attempts - 1 or not retry_budget.try_spend():
                raise
            sleep = random.uniform(0, min(cap, base * 2 ** n))      # full jitter
            if deadline and time.monotonic() + sleep >= deadline:
                raise
            time.sleep(sleep)

Что хотят услышать

  • Таймаут на каждый вызов и как выбирать значение.
  • Условия повтора: идемпотентность, какие ошибки.
  • Экспоненциальная отсрочка с джиттером и зачем джиттер.
  • Перемножение повторов, бюджет повторов, дедлайны.

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

  • Повторять неидемпотентный POST без ключа идемпотентности.
  • Ставить повторы на каждом уровне цепочки.

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем