Синхронный вызов или очередь: как выбрать способ интеграции
Практический разбор выбора между прямым API-вызовом, очередью, событием и асинхронной обработкой во внешней интеграции.
Почему этот выбор нельзя оставлять разработке “по месту”
Синхронный API-вызов выглядит проще: отправили запрос, получили ответ, продолжили сценарий. Но внешняя интеграция часто живет иначе. Ответ может задержаться, контур может быть недоступен, результат может прийти позже, а часть решений требует ручной проверки.
Если заранее не выбрать форму обмена, продуктовая логика начинает зависеть от технического ожидания. Пользователь ждет, процесс висит, повтор может создать дубль, а команда спорит, ошибка это или нормальное состояние.
Быстрый принцип выбора
Синхронный вызов подходит, когда ответ нужен прямо сейчас, время ожидания ограничено, отказ можно сразу показать пользователю, а внешний контур достаточно стабилен для такого сценария.
Асинхронный обмен подходит, когда внешняя сторона может обрабатывать запрос дольше, менять статус позже, требовать повторов, ручного разбора или отдельной проверки результата.
Очередь, событие, воркер или workflow-инструмент не делают интеграцию надежной сами по себе. Apache Kafka, RabbitMQ, Temporal и похожие инструменты помогают реализовать выбранную модель, но сначала нужно понять границу ответственности и жизненный цикл операции.
%%{init: {"flowchart": {"useMaxWidth": false}} }%%
flowchart TD
Start["Операция"] --> NeedNow{"Ответ нужен сразу?"}
NeedNow -->|Да| Sync["Sync API"]
NeedNow -->|Нет| Async["Async контур"]
Sync --> Rules["Timeout, ошибка, повтор"]
Async --> Rules
1. Когда уместен синхронный вызов
Синхронный вызов можно выбирать, если выполняются условия:
- результат нужен для продолжения текущего пользовательского действия;
- допустимое время ожидания понятно и коротко;
- ошибка может быть сразу превращена в понятный следующий шаг;
- повтор запроса безопасен или не нужен;
- внешний ответ является финальным, а не промежуточным;
- поддержке не нужно отдельно сопровождать долгую обработку.
Пример: проверить справочник, получить доступный тариф, валидировать формат, запросить быстрый статус, который не запускает дорогую внешнюю операцию.
2. Когда нужен асинхронный контур
Асинхронность стоит рассматривать, если есть хотя бы один признак:
- внешний контур может долго отвечать;
- результат может прийти позже отдельным событием или webhook;
- операция имеет несколько статусов;
- таймаут не означает, что операция не выполнена;
- повтор может создать дубль;
- нужна ручная проверка или операторское действие;
- система должна продолжать работать, даже если внешний контур временно недоступен.
В таком случае полезно описывать не “отправить запрос”, а процесс: создать операцию, отправить, ожидать, получить статус, повторить, разобрать вручную, завершить.
3. Как выглядит компромисс
Выбор не всегда бинарный. Часто рабочая схема состоит из двух уровней:
- пользовательский сценарий получает быстрый локальный статус: “заявка принята”, “проверка запущена”, “ожидаем ответ”;
- интеграционный контур отдельно обрабатывает внешний обмен, повторы, статусы и диагностику.
Так продукт не блокируется на внешнем ожидании, но пользователь и поддержка видят понятное состояние.
4. Вопросы перед выбором
Перед архитектурным решением пройдите короткий список:
- Кто инициирует операцию: пользователь, система, расписание, внешний контур?
- Нужен ли финальный результат до продолжения пользовательского сценария?
- Что происходит, если ответ не пришел?
- Можно ли повторить запрос без дубля?
- Есть ли внешний идентификатор операции?
- Будут ли промежуточные статусы?
- Кто увидит зависшую операцию?
- Какие данные нельзя потерять при сбое?
- Где будет источник истины по статусу?
Если ответы связаны с ожиданием, повторами и отдельными статусами, синхронный вызов как единственная модель почти наверняка слаб.
5. Как зафиксировать решение
Решение должно описывать:
- почему выбран синхронный или асинхронный обмен;
- что считается успешным результатом;
- какие ошибки являются финальными;
- какие ошибки переводят операцию в повтор;
- какие статусы видит продукт;
- где хранится состояние операции;
- как поддержка найдет запрос по идентификатору;
- какие условия заставят пересмотреть решение.
Это можно оформить как короткий decision record рядом с API-контрактом и моделью статусов.
Минимальный шаблон
| Вопрос | Ответ |
|---|---|
| Нужен ли результат прямо сейчас? | Да / нет / только предварительный статус |
| Что будет при таймауте? | Повтор, ожидание, проверка статуса, ручной разбор |
| Где живет состояние операции? | Локальная БД, очередь, workflow, внешний контур |
| Как защищаемся от дублей? | Idempotency key, operation id, дедупликация события |
| Что видит пользователь? | Финальный ответ или состояние обработки |
| Кто сопровождает сбой? | Система, оператор, поддержка, команда |
Если таблица не заполняется без догадок, выбранный способ интеграции еще не готов к разработке.