Ответ
Асинхронная коммуникация через шины (RabbitMQ, Kafka, AWS SQS) решает многие задачи масштабирования, но имеет ряд существенных недостатков:
- Сложность отладки и мониторинга. Трудно отследить полный путь сообщения (distributed tracing). Нет синхронного ответа об ошибке, проблемы могут проявиться с задержкой в другом сервисе.
- Нарушение порядка сообщений. В системах с несколькими консьюмерами или партициями (Kafka) нет гарантии, что сообщения
Событие A→Событие Bбудут обработаны в том же порядке. Это требует идемпотентности или специальной логики. - Потенциальное дублирование обработки. Из-за retry-механизмов, таймаутов или сбоев консьюмера одно и то же сообщение может быть обработано несколько раз.
- Задержки (latency). Не подходит для сценариев, требующих немедленного ответа пользователю (синхронный HTTP-запрос).
- Усложнение архитектуры и кода. Появляются новые сущности: очереди, обменники, dead-letter queues. Код должен обрабатывать повторные попытки, идемпотентность, компенсирующие транзакции (Saga pattern).
Пример проблемы с порядком:
// Сервис заказов публикует события
$messageBus->dispatch(new OrderCreated($orderId)); // Событие 1
$messageBus->dispatch(new OrderPaid($orderId)); // Событие 2
// Сервис доставки может получить их в порядке: 2, 1
// и попытаться начать доставку несуществующего заказа.
Для борьбы с этим в Kafka можно использовать ключ партиционирования (например, orderId), чтобы события одного заказа попадали в одну партицию и сохраняли порядок.