
Архитектура — это всегда баланс между контролем и гибкостью. Микросервисы (MSA) хороши тем, что чётко разделяют логику, дают независимое масштабирование и удобны в отладке. Каждый сервис сам за себя, отвечает за конкретную зону ответственности и общается с другими через API — обычно REST или gRPC. Вроде бы идеальная схема, но со временем возникает проблема: сервисов становится всё больше, а их связи усложняются. Появляется скрытая зависимость — если один сервис меняет контракт API, все клиенты должны адаптироваться. Итог: чем больше микросервисов, тем сильнее их взаимозависимость, что фактически превращает систему в «распределённый монолит».
Хороший пример — Amazon. Компания начинала с монолитного приложения, но со временем перешла к микросервисной архитектуре. Это позволило командам работать независимо, но привело к новым проблемам — например, сложностям с управлением версиями API и зависимостями между сервисами.
Теперь посмотрим на событийно-ориентированную архитектуру (EDA). Здесь сервисы не дергают друг друга напрямую, а просто публикуют события. Например, сервис регистрации отправляет событие «пользователь зарегистрирован», а уже подписчики решают, как на это реагировать: один создаст профиль в базе, другой отправит email, третий добавит запись в CRM. Сервису, который породил событие, вообще всё равно, кто его обработает — он просто выдал сигнал в шину сообщений (Kafka, RabbitMQ, Amazon EventBridge и т. д.).
На практике это даёт кучу плюсов. Во-первых, такая архитектура проще масштабируется: нагрузка распределяется, а новые подписчики могут подключаться без изменений в исходном сервисе. Во-вторых, отказоустойчивость выше: если один обработчик упадёт, события никуда не пропадут и будут обработаны позже. В-третьих, это отлично подходит для асинхронных задач, например, в e-commerce — заказ оформлен, а дальше система сама разруливает отправку уведомлений, списание денег и логистику без ожидания ответа от каждого сервиса.
Такую модель использует Netflix. Их система логирования и мониторинга построена на EDA: все сервисы стриминга, рекомендации, биллинга и аналитики обмениваются событиями через Kafka, что позволяет динамически масштабировать нагрузку.
Но у EDA тоже хватает минусов. Во-первых, дебаг. Если в микросервисах можно просто вызвать API и сразу увидеть результат, то тут события путешествуют по системе непредсказуемо. Откуда взялся баг? Какой сервис не обработал событие? Где оно вообще потерялось? Чтобы не утонуть в хаосе, приходится внедрять трассировку, ставить мониторинг, логировать каждую стадию обработки. Uber, например, использует OpenTelemetry и Jaeger для распределённого трейсинга, чтобы отслеживать движение событий между сотнями сервисов.
Во-вторых, сложность управления событиями. В реальной системе одно событие может триггерить десятки других процессов, а некоторые события могут дублироваться из-за проблем с сетью или задержек в обработке. Это значит, что нужно продумывать механику дедупликации и идемпотентности, чтобы случайно не создать дубликаты заказов или платежей. Airbnb столкнулись с этой проблемой при масштабировании системы бронирования — пришлось внедрять строгий контроль за повторной обработкой событий.
Так что же выбрать?
Если система требует строгой синхронности и предсказуемости — микросервисы. Если важна гибкость, отказоустойчивость и независимость компонентов — события.
Но идеальный вариант — это их комбинация. Критичные запросы (например, авторизация, платежи) лучше делать через API, чтобы избежать задержек и дублирования. А для второстепенных процессов (уведомления, аналитика, интеграции с внешними системами) можно использовать брокер сообщений.
Например, в маркетплейсе Amazon заказ можно оформить через REST API, но обработка идёт через событийную архитектуру:
Пользователь оформил заказ → сервис заказов сохранил данные в базе.
Событие «заказ создан» отправилось в шину.
Сервис платежей подписан на это событие → списал деньги.
Сервис логистики подписан → передал информацию на склад.
Сервис уведомлений подписан → отправил email клиенту.
Таким образом, каждое действие логически отделено от других, но вся система работает как единое целое.
Вывод простой: чем больше система, тем полезнее события, но полностью отказываться от API тоже не стоит. Главное — не упрощать архитектуру в ущерб масштабируемости.