В чем ключевое отличие Event-Driven Architecture от традиционной Request-Response модели?

Ответ

Основное отличие заключается в модели взаимодействия компонентов. В Event-Driven Architecture (EDA) компоненты общаются асинхронно через события, в то время как в Request-Response модели клиент отправляет запрос и синхронно ожидает ответа от сервера.

Ключевые отличия:

  • Связанность (Coupling):

    • EDA: Слабая связанность. Продюсер события не знает о его потребителях. Это позволяет добавлять или изменять потребителей, не затрагивая продюсера.
    • Request-Response: Сильная связанность. Клиент должен знать адрес и API сервера.
  • Поток управления:

    • EDA: Асинхронный и неблокирующий. Система реагирует на события по мере их поступления.
    • Request-Response: Синхронный и блокирующий. Клиент ждет, пока сервер обработает запрос.
  • Масштабируемость:

    • EDA: Легко масштабируется горизонтально. Можно добавить больше экземпляров сервисов-потребителей для обработки возросшего потока событий.
    • Request-Response: Масштабирование сложнее и часто требует балансировщиков нагрузки.

Практический пример (Python с RabbitMQ):

Представим сервис заказов, который после создания заказа должен уведомить сервис нотификаций.

Продюсер (сервис заказов):

# producer.py
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

channel.queue_declare(queue='order_created_events')

# Публикуем событие о создании заказа
message = '{"order_id": 123, "user_id": 45}'
channel.basic_publish(exchange='',
                      routing_key='order_created_events',
                      body=message)

print(f" [x] Sent {message}")
connection.close()

Потребитель (сервис нотификаций):

# consumer.py
import pika

def callback(ch, method, properties, body):
    print(f" [x] Received event: {body.decode()}. Sending notification...")
    # Логика отправки email или push-уведомления

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

channel.queue_declare(queue='order_created_events')
channel.basic_consume(queue='order_created_events',
                      on_message_callback=callback,
                      auto_ack=True)

print(' [*] Waiting for events. To exit press CTRL+C')
channel.start_consuming()

В этом примере сервис заказов не знает о существовании сервиса нотификаций, что делает систему гибкой и отказоустойчивой.