Ответ
Основное отличие заключается в модели взаимодействия компонентов. В 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()
В этом примере сервис заказов не знает о существовании сервиса нотификаций, что делает систему гибкой и отказоустойчивой.