Паттерн Event-driven architecture

Когда заканчивается кофе Event-driven Разработчики генерируют событие CoffeeLowException и ждут...

Контекст
ПРоблемный Толя:
Мы применили паттерн Database per service в нашем проекте интернет‑магазина диких ягод. Наделали кучу микров между которыми цепочки вызовов REST/HTTP, и теперь нам каждый раз больно, когда таймаут подвешивает поток в цепочке и пул потоков истощается.
Выручающая
Варвара:
Ну может circuit braker примените, уже рассматривали в прошлом видосе.
ПРоблемный Толя:
Circuit Breaker спасает сервис локально, но бизнес‑процесс рвётся, а компенсации «вручную». А плюс к этому когда контракты REST меняются — нужно одновременно катить несколько сервисов. Трудно ответить: «что случилось с заказом #123 так как логи распределённые и эфемерные. И плюс нельзя независимо масштабировать узкие места.
Выручающая
Варвара:
Тогда переходите на событийно‑ориентированную архитектуру (EDA)
Проблема
Как обеспечить высокую гибкость, масштабируемость, наблюдаемость и уменьшить латентность в микросервисной архитектуре?

Жёсткая временная связанность в синхронных цепочках (REST/HTTP): таймаут одной зависимости «кладёт» весь путь.
Каскадные сбои и «шторм ретраев» из-за повторных попыток на каждом уровне.
Слабая масштабируемость и head-of-line blocking под пиками нагрузки.
Сложные компенсации и размытый аудит бизнес-процессов.
Релизная связанность (версионирование REST DTO, «релизы в ногу»).
Решение
Представляем изменения в системе как неизменяемые факты (события), которые пишутся в надёжный лог (брокер).
Декуплинг по времени: продюсер публикует событие и не ждёт потребителя.
Композиция процессов через хореографию (реакции на события) или оркестрацию (саги/стейт-машина).
Управление согласованностью: идемпотентные обработчики, дедупликация, транзакционные пути (EOS), DLQ.
Наблюдаемость: события = журнал фактов → восстановление и анализ.

Транспорт/брокер: Kafka / Pulsar / RabbitMQ / NATS / Azure Event Hubs.
Стиль взаимодействия:
  • Publish/Subscribe (хореография доменов).
  • Команды + события (отдельные топики commands.* и events.*).
  • Оркестрация саг (центральный координатор, компенсации).
Паттерны данных:
  • Outbox + CDC (транзакционная публикация событий из БД).
  • Event Sourcing (состояние — это свёртка журнала событий).
  • CQRS (отдельно write-модель и read-проекции).
  • Schema Registry & эволюция схем (Avro/Protobuf/JSON-Schema).
Обработка потоков:
  • Kafka Streams / Spark Structured Streaming / Akka Streams / Reactor Kafka.
Гарантии доставки:
  • at-least-once + идемпотентность,
  • effectively/exactly-once для «consume→transform→produce» (транзакции, EOS v2 в Kafka Streams).
Преимущества
  • Не надо использовать распределенные транзакции
    EDA это способ уйти от сложных 2PC и 3PC, которые приводят к связанности сервисов и мы ограничены в использовании технологий, так они должны поддерживать распределенные транзакции.
  • Слабые связи благодаря асинхронному взаимодействию
    Как следствие слабых связей - гибкость, масштабируемость, отказоустойчивость
  • Упрощение интеграции
    EDA упрощает интеграцию с различными системами через стандартный механизм событий
  • Снижение хвостовой задержки (e2e p99)
    критический путь короче, пиковые нагрузки сглаживаются логом
Недостатки
  • Нет согласованности данных в моменте
    Что приводит к тому, что надо применять компенсирующие транзакции и такие паттерны как SAGA
  • Сложность отладки и тестирования
    В EDA время от возникновения события до его конечного воздействия может быть значительным, проходя через множество сервисов. Это делает сложным отслеживание и устранение проблем, требуя использования продвинутых инструментов, таких как распределенные трейсеры и логирование.
  • Нужно заботиться о порядке событий
    В распределенных системах события могут приходить не в том порядке, в котором они были сгенерированы. Это может приводить к логическим ошибкам, особенно в сценариях, где важна последовательность операций (например, в финансовых транзакциях). Для решения этой проблемы требуется использование ключей партиционирования и идемпотентных обработчиков
  • Необходимость в дополнительной инфраструктуре
    EDA требует наличия брокера сообщений, балансировщиков, средств мониторинга и других компонентов, что увеличивает затраты на инфраструктуру по сравнению с более простыми архитектурами.
Онлайн-школа профессионального программирования на java для коммерческих разработчиков и соискателей.
2 главные задачи, которые мы решаем:
  1. Трудоустройство и успешное прохождение испыталки.
  2. Переход на современный стек middle+
Наше главное достояние:
Менторская поддержка 24/7 и обучение в формате живого общения
Получить консультацию по обучению