Как работает архитектура интеграции с партнером на уровне компонентов и взаимодействия
Что проверяют
Вопрос почти всегда про вашу реальную интеграцию: кто инициирует обмен, что происходит при сбое партнёра и как вы гарантируете, что данные не потеряются и не задвоятся. Следом спрашивают про ретраи, идемпотентность и тестирование без живого партнёра.
Как отвечать
Опишите интеграцию как цепочку компонентов на примере своего проекта:
- адаптер (anti-corruption layer): модуль, который переводит модель партнёра в вашу доменную. DTO партнёра не протекают в бизнес-логику;
- клиент:
RestClientилиWebClientв Spring, декларативные HTTP-интерфейсы через@HttpExchange, клиент по OpenAPI-спецификации из openapi-generator; - аутентификация: OAuth 2.0 client credentials, mTLS или HMAC-подпись запросов, у входящих вебхуков обязательно проверка подписи;
- устойчивость: таймауты на соединение и чтение, ретраи с экспоненциальной задержкой и джиттером, circuit breaker и ограничение частоты под квоту партнёра, обычно через Resilience4j;
- асинхронная часть: transactional outbox, то есть запись события в той же транзакции, что и бизнес-данные, и отдельный процесс, который публикует его в Kafka или RabbitMQ. Входящие сообщения дедуплицируются по идентификатору;
- сверка: периодическое сравнение состояний с партнёром, потому что рано или поздно что-то разойдётся;
- наблюдаемость: correlation id в каждом запросе, метрики Micrometer, трассировка через OpenTelemetry, логи с маскированием персональных данных.
Тестирование назовите отдельно: WireMock вместо партнёра, контрактные тесты (Pact или Spring Cloud Contract), песочница партнёра перед продом.
Если опыта мало, опишите схему, которую спроектировали бы, и честно скажите, какие части делали сами, а какие видели со стороны.
Где спотыкаются
Ставят ретраи на неидемпотентный POST без ключа идемпотентности. Партнёр создал платёж, ответ потерялся по таймауту, ретрай создал второй.
Не задают таймауты. У ряда HTTP-клиентов ожидание по умолчанию бесконечное, и один зависший партнёр съедает весь пул потоков сервиса.
Пишут в базу и отправляют сообщение в Kafka в одном методе без outbox. При падении между двумя операциями одна система узнает о событии, а другая нет.