Идемпотентность в дизайне API: Webhooks и практические примеры
Идемпотентность обеспечивает, чтобы повторные вызовы API возвращали одинаковый результат. Это особенно важно для платежей, заказов и webhooks.
Краткое описание
Идемпотентность — свойство операций, которые можно выполнять многократно без изменения результата. В дизайне API она критична для надёжных и отказоустойчивых интерфейсов. GET, PUT и DELETE идемпотентны, POST, как правило, нет. Для неидемпотентных операций вроде POST или внешних вызовов типа webhooks используются Idempotency Keys, чтобы избежать повторного выполнения. Webhooks также должны быть идемпотентными, чтобы получатели могли обработать одинаковые события несколько раз без дублирования данных. Грамотная стратегия идемпотентности снижает ошибки, вызванные сетевыми сбоями, повторами и race conditions, значительно повышая надёжность API.
Ключевые компоненты
Идемпотентные HTTP-методы
GET идемпотентен, потому что не вызывает изменений состояния. PUT идемпотентен, так как полностью заменяет ресурс независимо от количества выполнений. DELETE идемпотентен, потому что после первого удаления ресурс больше не существует и последующие попытки удаления приводят к одному и тому же конечному состоянию. POST не идемпотентен, так как каждый вызов может создать новый ресурс.
Idempotency Keys
Idempotency Key — уникальное значение, которое клиент передаёт с запросом. Сервер сохраняет ключ и результат первого запроса. При повторном вызове с тем же ключом сервер возвращает сохранённый результат вместо повторного выполнения операции. Это особенно важно для платежей, бронирования и заказов.
Гарантированная идемпотентность платежей
В API платежей сетевой сбой может привести к повторному запросу со стороны клиента. Без Idempotency Key платёж может быть выполнен дважды. С ключом сервер гарантирует, что платёж выполнится только один раз, даже если клиент запросит несколько раз.
Webhooks и идемпотентность
Webhooks — события, отправляемые сервером клиенту. Из-за таймаутов или повторов они могут поступить несколько раз. Получатель должен обрабатывать webhooks идемпотентно, распознавая каждое событие по уникальному Event ID и отбрасывая или игнорируя дубликаты.
Retry-стратегии и идемпотентность
Клиенты должны автоматически повторять только идемпотентные операции. GET и PUT безопасно повторяются при сетевых ошибках. POST можно повторять только, если используется Idempotency Key. Иначе возможны нежелательные двойные списания.
Хранение Idempotency Keys
Idempotency Keys должны сохраняться на сервере в течение определённого времени. Хранилище может быть базой данных, кешем или отдельным сервисом. Важно, чтобы ключи были связаны с результатом операции и не могли быть переиспользованы для разных запросов.
TTL и сохранение
Idempotency Keys должны иметь определённое время жизни. По истечении TTL ключ можно удалить. Клиент должен знать, как долго ключ остаётся действительным, чтобы не переиспользовать его слишком поздно. Типичные значения TTL варьируются от минут до дней.
Избежание race conditions
Если два запроса с одинаковым Idempotency Key приходят одновременно, сервер должен убедиться, что выполняется только одна операция. Механизмы блокировки или атомарные операции БД помогают избежать race conditions.
Обработка ошибок с Idempotency Keys
Если Idempotency Key недействителен или истёк, API должна вернуть понятное сообщение об ошибке. Клиент может тогда решить, повторить операцию с новым ключом или отправить исходный запрос заново.
Мониторинг и логирование
Idempotency Keys и повторные запросы должны логироваться. Это помогает при отладке и позволяет выявить закономерности типа частых таймаутов или дублирования. Мониторинг может вовремя предупредить о проблемах.
Практический пример
Интернет-магазин предоставляет API для создания заказов. Клиент хочет убедиться, что заказ не будет случайно создан дважды.
Запрос с Idempotency Key:
POST /api/v1/orders
Content-Type: application/json
Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7
{
"customerId": 123,
"items": [
{ "productId": 42, "quantity": 2 }
]
}
Первое выполнение:
HTTP/1.1 201 Created
Location: /api/v1/orders/98765
{
"orderId": 98765,
"status": "created",
"total": 79.97
}
Повторный запрос с тем же ключом:
POST /api/v1/orders
Content-Type: application/json
Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7
{
"customerId": 123,
"items": [
{ "productId": 42, "quantity": 2 }
]
}
Сервер распознаёт ключ и возвращает одинаковый результат:
HTTP/1.1 201 Created
Location: /api/v1/orders/98765
{
"orderId": 98765,
"status": "created",
"total": 79.97
}
Webhook с Event ID:
POST /webhooks/orders
Content-Type: application/json
X-Event-ID: event-12345-abcde
{
"eventType": "order.created",
"orderId": 98765,
"status": "created"
}
Получатель сохраняет X-Event-ID и обрабатывает одинаковые ID только один раз. Так обработка остаётся идемпотентной, даже если webhook отправлен несколько раз.
FAQ: идемпотентность в дизайне API
1. Что такое идемпотентность?
2. Какие HTTP-методы идемпотентны?
3. Что такое Idempotency Key?
4. Почему идемпотентность важна для платежей?
5. Что такое webhook?
6. Почему webhooks должны быть идемпотентными?
7. Как распознать повторные webhooks?
8. Что происходит при одновременных запросах с одинаковым Idempotency Key?
9. Как долго следует сохранять Idempotency Key?
10. Может ли PATCH быть идемпотентным?
11. Что происходит при недействительном Idempotency Key?
12. Следует ли использовать Idempotency Keys для всех POST запросов?
13. Какова разница между идемпотентностью и Safe Methods?
14. Как тестировать идемпотентность?
15. Какова связь идемпотентности с retry-стратегиями?
Продолжение на пути обучения API
Следующий материал в цикле про API посвящён основам Webhook — как они устроены, как их безопасно реализовать и на что обратить внимание при проверке подписей.
Источники
- https://www.rfc-editor.org/rfc/rfc9110
- https://stripe.com/docs/api/idempotent_requests
- https://datatracker.ietf.org/doc/html/draft-ietf-httpapi-idempotency-key
Книги про разработку API
Если хочешь углубиться в идемпотентность, API дизайн и архитектуру программного обеспечения, вот несколько полезных книг:
Keine Bücher für Kategorie "api-development" gefunden.



