Event streaming и event-driven архитектура

Урок объясняет архитектурный сдвиг, который Kafka делает естественным: от команд к событиям.

Event-driven архитектура — стиль построения систем, где компоненты общаются, публикуя и потребляя события (факты о случившемся), а не вызывая друг друга напрямую.

Зачем это нужно

В классической архитектуре сервис заказов сам зовёт сервис уведомлений, потом склад, потом аналитику. Каждый новый потребитель события «заказ создан» — это правка в сервисе заказов. Он знает обо всех и зависит от всех. В event-driven подходе сервис заказов просто публикует факт «заказ создан» в Kafka и забывает о нём. Кто хочет — подписывается. Добавить потребителя теперь можно, не трогая источник.

Команда против события

КомандаСобытие
Смысл«сделай X»«X произошло»
Направленаконкретному адресатув никуда (кто хочет, читает)
Связьжёсткая (знает адресата)слабая (не знает читателей)
Пример«спиши деньги»«платёж выполнен»

Поток фактов как клей

  [ Сервис заказов ]
        |  публикует факт
        v
  ==== Kafka: топик "order.created" ====
        |          |            |
        v          v            v
   Склад     Уведомления    Аналитика
  (каждый реагирует сам, источник о них не знает)

Заметьте: стрелки идут только вниз — источник ничего не ждёт в ответ. Это и есть развязка во времени и в пространстве.

Реактивность

Event-driven системы реактивны: компонент «спит», пока не придёт событие, затем реагирует. Это снимает с источника ответственность за оркестрацию и распределяет работу. Цена — отказ от мгновенной согласованности: потребители обрабатывают факты с небольшой задержкой и в свой темп (eventual consistency).

Как работает под капотом

Kafka делает event-driven практичным, потому что хранит поток фактов. В системе на синхронных вызовах, если уведомления упали, событие теряется. В event-driven на Kafka событие лежит в логе: сервис уведомлений поднимется и дочитает с того оффсета, где остановился. Лог становится надёжным буфером и «источником истины» о том, что произошло. Источник публикует один раз — а сколько систем это прочитают и когда, его не касается.

Частые ошибки

  • Прятать команды под видом событий. Топик send_email с адресатом — это замаскированная команда, а не факт; настоящий факт — user.registered.
  • Ждать мгновенной согласованности. Event-driven — это eventual consistency; проектируйте под задержку.
  • Складывать в событие «толстое» состояние. Публикуйте факт и ключевые поля, а не весь объект целиком.

Итоги

  • Event-driven заменяет прямые вызовы публикацией фактов в общий лог.
  • Событие («X произошло») развязывает источник и потребителей во времени и пространстве.
  • Хранимый лог Kafka делает реактивные системы надёжными: упавший потребитель дочитает позже.
Проверьте себя
1. Чем событие отличается от команды?
AСобытие быстрее доставляется
BСобытие сообщает «X произошло» и не знает адресата, команда говорит «сделай X» конкретному получателю
CКоманда не сохраняется
DЭто синонимы
2. Почему event-driven системы на Kafka устойчивы к падению потребителя?
AKafka повторяет вызов синхронно
BСобытие хранится в логе, и потребитель дочитает его с нужного оффсета после восстановления
CПотребители не падают
DИсточник ждёт ответа
3. Что характерно для event-driven архитектуры?
AСтрогая мгновенная согласованность
BEventual consistency: потребители обрабатывают события с задержкой в свой темп
CОтсутствие задержек вообще
DИсточник знает всех потребителей