В интеграциях корпоративных систем часто спорят не о том, как связать системы, а о том, чем именно их связать: REST API, webhook или брокером сообщений.
На практике универсального ответа нет. REST удобен, когда одной системе нужен ответ другой прямо сейчас. Webhook — когда система должна сообщить о произошедшем событии. Брокер — когда сообщения нужно доставлять асинхронно, независимо от доступности отдельных потребителей.
Ошибка обычно возникает не при выборе конкретной технологии, а когда один механизм пытаются использовать для всех сценариев.
Разберём три подхода на практических примерах и посмотрим, где проходит граница между ними.
REST: когда одна система прямо спрашивает другую
Сайт запрашивает у 1С остаток товара и ждёт ответ здесь и сейчас, прежде чем показать карточку товара покупателю.
Это классический сценарий REST API: одна система отправляет HTTP-запрос, другая его обрабатывает и возвращает ответ.
Условно:
Сайт → GET /products/123/stock → 1С → остаток: 7 → Сайт
Главное преимущество такого подхода — предсказуемость. Отправили запрос, получили ответ или ошибку и можем сразу продолжить обработку.
REST хорошо подходит, когда:
- ответ нужен непосредственно в момент выполнения операции;
- запрос относительно лёгкий;
- результат нужен только инициатору запроса;
- допустима зависимость от доступности системы, к которой обращаемся.
Например:
- проверить остаток товара;
- получить карточку клиента;
- рассчитать стоимость доставки;
- проверить доступность услуги;
- авторизовать пользователя.
Где REST начинает создавать проблемы
Представим интернет-магазин, который при оформлении каждого заказа синхронно обращается к 1С.
Пока 1С отвечает быстро, всё работает нормально. Но если она под нагрузкой начинает отвечать по несколько секунд, сайт вынужден ждать. Если 1С временно недоступна, приложению приходится самостоятельно решать, что делать: повторять запрос, показывать ошибку, ставить операцию в очередь или использовать резервный сценарий.
REST сам по себе не означает, что система обязательно «зависнет». Таймауты, повторные попытки (retries), circuit breaker, асинхронная обработка и другие механизмы позволяют снизить последствия таких сбоев.
Проблема в другом: при синхронной интеграции доступность одной системы начинает влиять на выполнение операции в другой.
Если это нормально для конкретного сценария — REST остаётся простым и хорошим выбором.
Webhook: когда система сама сообщает о событии
Платёжный сервис не заставляет ваш сервер постоянно спрашивать:
«Оплата прошла? А сейчас? А сейчас?»
Вместо этого он сам отправляет HTTP-запрос на заранее заданный endpoint, когда происходит событие.
Например:
Платёжная система → POST /webhooks/payment → Ваш сервер
В запросе может быть информация о платеже, его статусе и идентификаторе события.
Это webhook: система-источник сама сообщает другой системе, что что-то произошло.
Подход особенно удобен для событий, которые возникают независимо от действий получателя:
- платёж проведён;
- статус доставки изменился;
- документ подписан;
- заказ отменён;
- пользователь подтвердил действие.
Главное преимущество webhook перед постоянным polling — не нужно регулярно спрашивать систему об изменениях. Событие отправляется тогда, когда оно произошло.
Но webhook — это не гарантия доставки
И здесь появляется одна из самых частых проблем.
Допустим, платёжный сервис отправил webhook, но ваш сервер в этот момент:
- перезапускается;
- перегружен;
- находится на деплое;
- временно недоступен из-за сетевой ошибки.
Если отправитель поддерживает повторную доставку, он не получит успешный HTTP-ответ и отправит то же событие ещё раз.
Поэтому обработчик webhook должен быть рассчитан на повторную доставку.
Обычно для этого:
- у события есть уникальный идентификатор;
- сервер проверяет, обрабатывалось ли событие раньше;
- повторное событие не приводит к повторному выполнению бизнес-операции.
Например, если webhook с event_id=12345 уже обработан, второй такой же запрос не должен повторно создавать заказ. Проверку идентификатора и изменение данных нужно согласовать так, чтобы два одновременных запроса тоже не выполнили операцию дважды.
Это называется идемпотентной обработкой.
Бывает и обратная ситуация: попытки исчерпаны или отправитель вообще не повторяет запросы — и событие можно пропустить. Для критичных операций полезна сверка с источником через его API: например, периодически сравнивать статусы оплат и восстанавливать пропущенные события.
Также для webhook стоит предусмотреть проверку подписи запроса, таймауты, журналирование и понятную стратегию повторной обработки ошибок.
Когда выбирать webhook
Webhook хорошо подходит, когда:
- источник события находится вне вашей системы;
- вам нужно получать уведомления о событиях;
- реакция может происходить асинхронно;
- вам не нужно постоянно опрашивать внешний сервис.
Например, платёжная система сообщает об успешной оплате, после чего ваше приложение запускает дальнейшую обработку заказа.
Message Broker: когда систем становится много
Теперь представим заказ на складе.
После его создания нужно:
- обновить остаток;
- передать информацию в CRM;
- отправить уведомление клиенту;
- передать данные в аналитическую систему;
- запустить дальнейшую обработку на складе.
Можно построить прямые интеграции:
Система заказов → CRM Система заказов → склад Система заказов → уведомления Система заказов → BI
Но со временем такая архитектура начинает обрастать зависимостями. Система заказов должна знать, куда отправлять данные, что делать при ошибке CRM и сколько раз повторять запрос.
Вместо этого можно использовать брокер сообщений:
→ CRM Система заказов → Broker → склад → уведомления → BI
Система заказов публикует событие, например order.created.
Дальше заинтересованные сервисы получают его независимо друг от друга.
В зависимости от конкретной технологии и настроек брокер может обеспечивать хранение сообщений, повторную доставку, подтверждение обработки и другие механизмы надёжности.
В качестве инфраструктуры обмена сообщениями могут использоваться, например, RabbitMQ или Kafka. В корпоративной среде функции обмена сообщениями также могут быть частью более широкой интеграционной или ESB-платформы.
Главный выигрыш — развязка систем
Системе заказов больше не нужно синхронно ждать ответа CRM при публикации события.
Если CRM временно недоступна, сообщение может остаться в инфраструктуре обмена и быть обработано позже — если такая модель доставки настроена в используемой системе. При повторной доставке брокер может передать сообщение ещё раз, поэтому потребителям тоже нужна идемпотентная обработка.
Это позволяет разделить:
производителя события и потребителей события.
Но за это приходится платить сложностью.
Появляется дополнительная инфраструктура, которую нужно:
- развернуть;
- мониторить;
- масштабировать;
- резервировать;
- обновлять;
- контролировать с точки зрения безопасности.
Кроме того, отладка распределённой системы сложнее. Если событие прошло через несколько сервисов, разобраться в проблеме только по логам одного приложения уже не получится.
REST, Webhook или Broker: как выбрать
Упрощённое правило можно свести к трём вопросам.
1. Мне нужен ответ прямо сейчас?
Да → REST.
Например, нужно узнать остаток товара перед тем, как показать его покупателю.
2. Другая система должна сообщить мне о событии?
Да → Webhook.
Например, платёжный сервис должен сообщить об успешной оплате.
3. Одно событие должны независимо обработать несколько систем?
Часто да → Message Broker, если получателям нужна независимая обработка, повторная доставка или буферизация.
Например, после создания заказа информацию одновременно должны получить склад, CRM, уведомления и аналитика.
Но есть важная оговорка: это не три взаимоисключающих варианта.
В реальном проекте они часто работают вместе.
Когда webhook и broker используются одновременно
Например, внешняя платёжная система отправляет webhook после успешной оплаты.
Первый участок интеграции может выглядеть так:
Платёжная система → Webhook → API вашего сервиса
API принимает событие, проверяет подпись и уникальность события, а затем публикует его во внутренний брокер:
Webhook → API → Message Broker
Успешный ответ отправителю следует возвращать после надёжного сохранения события. Если API вернул 200, а публикация в брокер не удалась, событие может потеряться. Один из способов закрыть этот разрыв — сначала сохранить событие в базе, а затем передать его в брокер отдельным процессом. Если одновременно меняются бизнес-данные, событие и изменения можно записать в одной транзакции по схеме transactional outbox. Публикация при этом всё равно может повториться, поэтому потребителям нужна идемпотентность.
Дальше уже внутренние сервисы подписываются на нужные события:
→ Сервис заказов Message Broker → CRM → Уведомления → Аналитика
В таком варианте webhook решает одну задачу — доставляет событие от внешней системы внутрь вашей инфраструктуры.
А брокер решает другую — распределяет событие между внутренними потребителями и снижает связанность между ними.
Выбирать механизм стоит для конкретного участка взаимодействия, а не один на весь проект.
А если событие нужно только одной системе?
Тогда брокер может оказаться избыточным.
Допустим, сервис доставки отправляет webhook об изменении статуса заказа, а обработать его должен только один небольшой сервис.
Поднимать отдельную брокерную инфраструктуру только ради этого события может быть неоправданно.
Webhook здесь проще:
Сервис доставки → Webhook → Ваш API
А если обработка события становится критичной, появляются десятки потребителей или нужен устойчивый асинхронный обмен, архитектуру можно усложнить позже.
Не стоит добавлять распределённую инфраструктуру раньше, чем появляется реальная потребность в ней.
Что выбрать: короткая шпаргалка
| Сценарий | Подход |
|---|---|
| Нужно получить ответ прямо сейчас | REST |
| Нужно выполнить операцию и сразу узнать результат | REST |
| Внешняя система сообщает о событии | Webhook |
| Нужно отказаться от постоянного polling | Webhook |
| Одно событие независимо обрабатывают несколько сервисов | Message Broker |
| Нужна буферизация при недоступности получателей | Message Broker с настроенным хранением сообщений |
| Нужна асинхронная обработка большого потока событий | Message Broker |
| Событие приходит извне, а внутри его обрабатывают несколько сервисов | Webhook + Message Broker |
Где чаще всего ошибаются
Есть три типичные архитектурные ошибки.
Первая — использовать REST для всего.
Так появляются цепочки синхронных вызовов, где одна операция зависит сразу от нескольких сервисов.
Вторая — использовать webhook без идемпотентности.
Повторная доставка события становится причиной дублей или повторного выполнения бизнес-операции.
Третья — ставить брокер там, где достаточно обычного HTTP-запроса.
Брокер — не универсальное средство «сделать архитектуру надёжнее». Это дополнительная инфраструктура со своей стоимостью и сложностью.
Поэтому вопрос стоит формулировать не как:
«Что лучше — REST, webhook или Kafka?»
А как:
«Какой способ взаимодействия соответствует требованиям именно этого участка системы?»
Итог
REST, webhook и message broker решают разные задачи.
REST — когда нужно обратиться к другой системе и получить ответ.
Webhook — когда система должна сообщить о произошедшем событии через HTTP.
Message broker — когда события нужно обрабатывать асинхронно и независимо распределять между несколькими потребителями.
В зрелой архитектуре эти подходы не конкурируют друг с другом. Один и тот же процесс может использовать все три:
REST — для синхронного запроса данных, Webhook — для получения события от внешней системы, Broker — для дальнейшего распределения этого события внутри инфраструктуры.
Выбор зависит от того, нужен ли ответ сразу, кто инициирует обмен и что должно происходить при сбое одного из участников.