Как правильно настраивать таймауты и повторы запросов?
- Что такое экспоненциальная отсрочка с джиттером?
- Что такое retry budget?
- Как передавать дедлайн по цепочке вызовов?
Таймаут у каждого сетевого вызова — по p99.9 зависимости, а не «по умолчанию». Повторы — только идемпотентных операций, с экспоненциальной отсрочкой и джиттером, ограниченным числом и бюджетом.
- Повторы на каждом уровне цепочки перемножаются: 3 уровня × 3 попытки = 27 запросов вниз
- Retry budget: повторы не больше ~10% от обычных запросов
- Дедлайн передаётся вниз: нижние сервисы не работают дольше, чем ждёт верхний
А ещё Не повторять 4xx (кроме 429), повторять таймауты и 5xx осторожно
Подробно
Таймауты. Без таймаута зависший ответ навсегда занимает поток, соединение и память — так медленная зависимость останавливает весь сервис. Нужны раздельно: на установку соединения (короткий) и на ответ. Значение — от измеренного распределения задержек зависимости (около 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 без ключа идемпотентности.
- Ставить повторы на каждом уровне цепочки.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Повторять любые запросы, включая неидемпотентные платежи
- ✗Таймауты по умолчанию библиотеки всегда подходят
- ✓Таймаут на каждый вызов; повторы идемпотентных с джиттером
- ✗Повторы на каждом уровне цепочки безопасны и не умножаются
Связанные вопросы
- В цепочке из трёх сервисов каждый повторяет неудачный вызов до трёх раз. Нижний сервис кратковременно деградировал. Чем это закончится? Middle
- Внешний платёжный провайдер начал отвечать за 30 секунд вместо 200 миллисекунд. Через минуту сервис перестал отвечать вообще, включая страницы, не связанные с оплатой. Что произошло? Middle
- В каких состояниях бывает circuit breaker и как он между ними переходит? Middle
- Как сервису пережить нагрузку выше его возможностей? Senior
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.