Logo GH

Політики повторів і backoff

Повтори (retries) допомагають пережити тимчасові збої, але при неправильному налаштуванні викликають лавини трафіку, дублі операцій і каскадні падіння. Надійна політика ретраїв завжди починається з дедлайнів/таймаутів, враховує ідемпотентність і використовує backoff + джиттер.

1) Базові принципи

1. Спочатку таймаут/дедлайн, потім ретрай. Повтор без межі часу лише подовжує відмову.
2. Ретрай - тільки для безпечних/ідемпотентних операцій. Для небезпечних - через idempotency-keys і транзакційні гарантії.
3. Backoff обов'язковий. Експоненціальний або GCRA-подібний з джиттером, щоб розсинхронізувати хвилі.
4. Обмежуйте кількість спроб і загальну бюджет-часу. Не виходьте за SLO користувача.
5. Поважайте сигнали інфраструктури.'429/503'+'Retry-After', стан circuit breaker, ліміти черг.

2) Таймаути і дедлайни (deadline propagation)

Таймаут запиту <SLO сервісу, дедлайн поширюється вниз по ланцюжку (HTTP заголовки/gRPC context).
Композиція таймаутів: сумарно (перша спроба + backoff + наступні) ≤ користувацький дедлайн.
Різні таймаути для читань/записів: записи коротше і суворіше; читання допускають hedging.

3) Ідемпотентність і безпечні повтори

Читання (GET/ідемпотентні RPC): безпечно повторювати при «5xx», «UNAVAILABLE», мережевих таймаутах.

Записи:
  • Використовуйте'Idempotency-Key'( HTTP) або request-ID на кордоні; сервер повинен дедуплікувати.
  • Пишіть ідемпотентні обробники: «upsert», «at-least-once» + компенсації (сага).
  • Зовнішні платежі/взаєморозрахунки - тільки з ідемпотентними ключами і журналом операцій.

4) Алгоритми backoff

Exponential: 'base 2 ^ attempt', обмежений'max _ backoff'.
Decorrelated Jitter (full/equal jitter): випадковість в діапазоні для розсинхронізації клієнтів.
GCRA/Token-Bucket-подібні затримки: узгоджені з rate limits.
Межі: 'initial _ backoff'( 50-200 мс читання; 200-500 мс запису),'max _ backoff'( 1-5 с),'max _ elapsed'( наприклад, 3-10 с).

Рекомендований шаблон: експоненціальний backoff + full jitter.

5) Політики прийняття рішення «повторювати/не повторювати»

Повторюємо при:
  • Мережевих помилках/таймаутах,'429'( з повагою'Retry-After'), «м'яких»'5xx'('502/503/504'), gRPC'UNAVAILABLE/DEADLINE _ EXCEEDED'.
Не повторюємо при:
  • «4xx» (крім «409/429/408» в деяких сценаріях), бізнес-помилках, «401/403», валідаційних помилках, явному «DoNotRetry» прапорі.
Розумні винятки:
  • '409 Conflict'- іноді повтор із затримкою після консенсусу/локів.
  • «404» для eventually consistent читань - одно-дворазовий ретрай з малим backoff.

6) Concurrency caps і «шторм ретраїв»

Обмежте одночасні ретраї per-client/per-tenant/per-endpoint.
Сумарний ліміт спроб на запит (наприклад, 2-3).
Гальмуйте «гарячі» ендпойнти через admission control, щоб не роздувати черги.

7) Взаємодія з Circuit Breaker і лімітами

Якщо CB open, не виконуйте ретраї безпосередньо - йдіть в fallback або чекайте'half-open'проб.
При'429'- поважайте'Retry-After'; при його відсутності - застосовуйте «м'який» backoff.
Ретраї можуть збільшувати навантаження; застосовуйте адаптивні пороги (знижуйте'max _ attempts'при інциденті).

8) Протоколи та контракти

HTTP

Коди: `408/429/5xx`.
Заголовки: 'Retry-After', сімейство'RateLimit-','Idempotency-Key','Request-Id'.
Клієнт повинен передавати'X-Request-Timeout '/' Deadline-At'( якщо у вас так прийнято).

gRPC

Використовуйте контекст з дедлайном; поважайте'UNAVAILABLE','DEADLINE _ EXCEEDED', поліси ретраїв на метод.
Для ідемпотентних RPC - включайте ретраї; для мутацій - тільки за підтримки ідемпотентності.

9) Черги, фонові завдання та інтеграції

At-least-once обробники → ідемпотентні дії, дедуплікація по ключу.
Delay queue для backoff між спробами (наприклад, 5s/30s/2m).
Dead-letter queue (DLQ) з лімітом спроб і ручною обробкою.
Outbox/CDC - щоб повтори не порушували транзакційну цілісність.

10) Hedging vs Retries

Hedging (дзеркальний запит) корисний для висококритичних читань при хвостовій латентності.
Обмежте: не частіше X% запитів, затримка «старт-грейс» (наприклад, p95-латентності), скасування переможених.
Не застосовуйте hedging до операцій запису без сильної ідемпотентності.

11) Телеметрія і спостережуваність

Теги: `tenant_id`, `endpoint`, `attempt`, `decision` (retry/skip), `reason`, `backoff_ms`, `deadline_ms`, `idempotency_key`.
Метрики: частка ретраїв, успішність після ретраїв, p95/p99 «end-to-end», кількість перевищених дедлайнів, спрацьовування CB.
Логи аудиту: верхні N «галасливих» ключів/ендпойнтів, кореляція з 429/503.

12) Тестування і хаос

Профілі: «пила» (burst-затишшя), «шторм» (масові таймаути), «липкі» помилки (кожен N-й), хвости латентності.
Відмови стора лімітера/кеша/черги, clock-skew.
Перевірка, що загальна тривалість (attempts + backoff) укладається в SLO.

13) Псевдокод політики

pseudo handle(req, deadline):
attempt = 0 backoff = initial()
while attempt < MAX_ATTEMPTS and now() < deadline:
attempt += 1 with timeout(per_attempt_timeout(deadline, attempt)):
try:
resp = call(req)
if isRetryableStatus(resp): raise Retryable(resp. status)
return resp except Retryable as e:
if circuit. isOpen(dep) or! isIdempotent(req): break sleep(jitter(backoff))
backoff = min(exp(backoff), MAX_BACKOFF)
except NonRetryable:
break return fail_or_fallback(req)

14) Конфігураційний шаблон (приклад)

yaml retries:
default:
max_attempts: 3 initial_backoff_ms: 150 max_backoff_ms: 2000 strategy: exponential_full_jitter respect_retry_after: true per_attempt_timeout_fraction: 0. 4 # 40% of remaining deadline hedging:
enabled: false read_heavy:
max_attempts: 4 initial_backoff_ms: 80 max_backoff_ms: 1200 hedging:
enabled: true start_after_p95_ms: 300 max_extra_requests_ratio: 0. 05 write_strict:
max_attempts: 2 initial_backoff_ms: 250 max_backoff_ms: 1000 idempotency_required: true

limits:
concurrent_retries_per_tenant: 100 concurrent_retries_per_endpoint: 20

15) Чек-лист перед продом

  • Дедлайни поширюються крізь виклики; сумарна тривалість ≤ SLO.
  • Алгоритм backoff з джиттером; параметри валідовані навантажувальним тестом.
  • Ідемпотентність: ключі/журнали/компенсації для записів.
  • Ретрай-політики розрізняються для читань і записів; respect `Retry-After`.
  • Конкурентність ретраїв і загальне число спроб обмежені.
  • Інтеграція з circuit breaker і rate limits налаштована.
  • Телеметрія: теги, метрики, логи причин; дашборди p95/p99, частка успіхів після ретраїв.
  • Тести «штормів» і хвостів латентності, DLQ для завдань.
  • Документація для клієнтів: коди/заголовки, приклади backoff і відміни.

16) Типові помилки

Повтори без таймаутів/дедлайнів - «вічні очікування».
Фіксовані паузи без джиттера - синхронні хвилі і DDoS-самосаботаж.
Ретраї небезпечних записів без ідемпотентності - дублі і розсинхронізація.
Ігнорування «Retry-After» і сигналів CB - ескалація інциденту.
Вузькі місця в чергах через відсутність caps і admission control.
Відсутність телеметрії причин/рішень ретраїв - «сліпий політ».

17) Швидкі рецепти

Публічні читання API: 3 спроби,'initial = 100ms','max = 1s', full jitter, hedging до 5% трафіку.
Критичні записи (платіж): 1-2 спроби макс, строгий таймаут, обов'язковий'Idempotency-Key', без hedging.
Зовнішні інтеграції: поважати'429/Retry-After','max _ attempts = 3','max _ backoff = 2-5s', ліміти на вихідний потік.
Фонові завдання: delay-backoff (5s → 30s → 2m), DLQ, ідемпотентні обробники.

Висновок

Хороша політика повторів - це баланс між швидким відновленням і контрольованою відмовою. Дедлайни, ідемпотентність, експоненціальний backoff з джиттером, обмеження конкуренції і повага сигналів інфраструктури перетворюють ретраї з «шторму» в інструмент підвищення надійності і утримання SLO.

Contact

Зв’яжіться з нами

Звертайтеся з будь-яких питань або за підтримкою.Ми завжди готові допомогти!

Telegram
@Gamble_GC
Розпочати інтеграцію

Email — обов’язковий. Telegram або WhatsApp — за бажанням.

Ваше ім’я необов’язково
Email необов’язково
Тема необов’язково
Повідомлення необов’язково
Telegram необов’язково
@
Якщо ви вкажете Telegram — ми відповімо й там, додатково до Email.
WhatsApp необов’язково
Формат: +код країни та номер (наприклад, +380XXXXXXXXX).

Натискаючи кнопку, ви погоджуєтесь на обробку даних.