Gymterview
middle

Что такое Event-Driven Architecture (EDA)

Event-Driven Architecture (EDA) — архитектурный стиль, в котором компоненты системы взаимодействуют посредством событий. Событие — факт, который произошёл в системе (например, «Платёж совершён», «Клиент зарегистрирован»). По аналогии с реальной жизнью: когда в банке совершается операция, кассир не обзванивает все отделы лично, а выписывает документ, который далее маршрутизируется по нужным адресатам.

Схема взаимодействия

Пример
┌─────────────┐   PaymentCreated   ┌──────────────┐
│  Сервис     │───────────────────▶│  Брокер      │
│  Платежей   │                    │  сообщений   │
└─────────────┘                    │  (Kafka)     │
                                   └──────┬───────┘
                                          │
                         ┌────────────────┼────────────────┐
                         ▼                ▼                ▼
                  ┌────────────┐  ┌────────────┐  ┌────────────┐
                  │  Сервис    │  │  Сервис    │  │  Сервис    │
                  │ Уведомлений│  │  Аналитики │  │  Комплаенс │
                  └────────────┘  └────────────┘  └────────────┘

Основные топологии EDA

1. Broker Topology (через брокер) — все события публикуются в брокер (Kafka, RabbitMQ), подписчики сами забирают нужные. Нет центрального оркестратора.

2. Mediator Topology (через посредник) — центральный компонент (медиатор) координирует обработку события, рассылая команды обработчикам.

Типы событий

  • Event Notification — уведомление о факте. Содержит минимум данных. Подписчик сам запрашивает детали при необходимости.
  • Event-Carried State Transfer — событие несёт в себе все необходимые данные, чтобы подписчик мог обработать его без дополнительных запросов.
  • Domain Event — событие, имеющее смысл в домене бизнеса (PaymentExecuted, AccountBlocked).

Пример на Spring с Kafka

Пример кода
// Публикация события
@Service
public class PaymentService {

    private final KafkaTemplate<String, PaymentEvent> kafkaTemplate;

    @Transactional
    public void executePayment(PaymentCommand cmd) {
        Payment payment = createAndSavePayment(cmd);

        kafkaTemplate.send("payment-events",
            new PaymentExecutedEvent(payment.getId(), payment.getAmount(),
                LocalDateTime.now()));
    }
}

// Подписчик
@Component
public class NotificationEventHandler {

    @KafkaListener(topics = "payment-events", groupId = "notification-service")
    public void onPaymentExecuted(PaymentExecutedEvent event) {
        notificationService.sendPaymentConfirmation(event);
    }
}

Плюсы

  • Слабая связанность (low coupling) — продюсер не знает о подписчиках.
  • Масштабируемость — можно добавлять подписчиков без изменения продюсера.
  • Отказоустойчивость — сбой одного подписчика не влияет на остальных.
  • Асинхронность — высокая пропускная способность.

Минусы

  • Сложность отладки и трассировки.
  • Eventual consistency вместо немедленной согласованности.
  • Необходимость обрабатывать дублирование событий (идемпотентность).
  • Сложность гарантии порядка обработки.

На собеседовании: Интервьюер хочет услышать о различии между типами событий (Notification vs Event-Carried State Transfer) и понимание eventual consistency. Частая ошибка — не упоминать проблему идемпотентности обработки событий.