Pepelen
← Системный анализ: API, интеграции и данные

Урок

Сбои: таймауты, повторы и идемпотентность

Описать в спецификации поведение интеграции при сбоях: таймаут, какие ошибки повторять и с какими паузами, ключ идемпотентности, отбрасывание дублей, очередь недоставленных сообщений и outbox.

1 / 8

Когда ответа нет

Когда ответа нет

Таймаут — не отказ. Если ответ не пришёл, операция могла выполниться: деньги списаны, а ответ потерялся по дороге. Неизвестный исход — главный источник дублей. Повторяют только исходы, которые могут пройти со второго раза, — они в таблице ниже. Повторы ограничивают: • число попыток, например 3; • паузы растут вдвое (1 с, 2 с, 4 с…) и сдвигаются на случайную величину (jitter), чтобы тысячи клиентов не ударили одновременно; • общий бюджет времени на все попытки. Ключ идемпотентности. Безопасно повторять только идемпотентное, а POST /orders не идемпотентен. Поэтому клиент генерирует уникальный Idempotency-Key (UUID) на одну попытку оформления и шлёт его в каждом повторе. Сервер хранит ключ с результатом (например, 24 часа) и на повтор возвращает тот же ответ. Тот же ключ с другим телом — ошибка, обычно 422. Это устоявшаяся практика (Stripe и др.) и черновик IETF, а не RFC. Получатель событий отбрасывает дубли (Idempotent Receiver): хранит обработанные eventId в таблице processed_events и пропускает повторы. Сообщение, которое не обработалось за N попыток или битое, уходит в очередь недоставленных сообщений (DLQ), чтобы не стопорить остальные; за DLQ следят и разбирают её. Двойная запись: заказ сохранён в базе, а событие в брокер не ушло (или наоборот). Решение — transactional outbox: событие пишется в таблицу outbox в той же транзакции, что и заказ, а отдельный процесс публикует его в брокер — хотя бы раз.
Исход → действие
ИсходПовторять?Как
таймаут, обрыв связидатолько если операция идемпотентна или есть ключ
502 / 503 / 504дас растущей паузой и jitter
429дапосле паузы из Retry-After
400 / 422нетисправить запрос; битое сообщение — в DLQ
401 / 403 / 404нетбез исправления ответ будет тем же
409нетперечитать состояние ресурса
Конспект урока
Когда ответа нет
Таймаут — не отказ. Если ответ не пришёл, операция могла выполниться: деньги списаны, а ответ потерялся по дороге. Неизвестный исход — главный источник дублей. Повторяют только исходы, которые могут пройти со второго раза, — они в таблице ниже. Повторы ограничивают: • число попыток, например 3; • паузы растут вдвое (1 с, 2 с, 4 с…) и сдвигаются на случайную величину (jitter), чтобы тысячи клиентов не ударили одновременно; • общий бюджет времени на все попытки. Ключ идемпотентности. Безопасно повторять только идемпотентное, а POST /orders не идемпотентен. Поэтому клиент генерирует уникальный Idempotency-Key (UUID) на одну попытку оформления и шлёт его в каждом повторе. Сервер хранит ключ с результатом (например, 24 часа) и на повтор возвращает тот же ответ. Тот же ключ с другим телом — ошибка, обычно 422. Это устоявшаяся практика (Stripe и др.) и черновик IETF, а не RFC. Получатель событий отбрасывает дубли (Idempotent Receiver): хранит обработанные eventId в таблице processed_events и пропускает повторы. Сообщение, которое не обработалось за N попыток или битое, уходит в очередь недоставленных сообщений (DLQ), чтобы не стопорить остальные; за DLQ следят и разбирают её. Двойная запись: заказ сохранён в базе, а событие в брокер не ушло (или наоборот). Решение — transactional outbox: событие пишется в таблицу outbox в той же транзакции, что и заказ, а отдельный процесс публикует его в брокер — хотя бы раз.