Я работаю над архитектурой микросервисного решения, в котором большая часть кода будет написана на C# и, скорее всего, на Angular для любого внешнего интерфейса. Мой вопрос касается цепочки сообщений. Я все еще выясняю, какой брокер сообщений использовать; Служебная шина Azure, RabbitMQ и т. д. Существует концепция, о которой я мало что нашел.
Как мне обрабатывать случаи, когда я хочу запустить сообщение, когда был запущен определенный набор сообщений. Пример, но не часть моего фактического решения: я хочу сказать «Уведомлять кого-то, когда оплачивает счет». Мы отправляем сообщение "PAIDBILL"
который запустит микросервисы, которые будут обрабатываться независимо:
FinanceService для дебетования бухгалтерской книги и увольнения
"PaymentPosted"
EmailService: электронное письмо, в котором клиент говорит спасибо за оплату счета
"CustomerPaymentEmailSent"
DiscountService: проверьте, получают ли они скидку за своевременную оплату, а затем отправьте
"CustomerCanGetPaymentDiscount"
Если все три сообщения сработали для одного и того же PAIDBILL
: Message "PaymentPosted"
, "CustomerPaymentEmailSent"
, "CustomerCanGetPaymentDiscount"
затем я хочу сообщить клиенту по электронной почте, что он получит скидку на свой следующий счет. Это должно быть сделано ПОСЛЕ того, как все три сработали, и порядок не имеет значения. Как запланировать отправку нового сообщения "EmailNextTimeDiscount"
сообщения, не опрашивая, какие сообщения отправляются каждую минуту, час, день?
Все, о чем я могу думать, это иметь таблицу SQL, которая отмечает, что каждая из них завершена (путем блокировки таблицы), и когда последняя заполнена, отправляет сообщение. Будет ли это хорошим решением? Я нахожу это анти-шаблоном для дизайна микросервисов и очередей сообщений.
1 ответ
Если вы используете сообщения (например, Service Bus/RabbitMQ), то я думаю, что описанное вами решение является лучшим. Этот тип проектирования, при котором сервисы обладают знаниями о других областях системы, обычно называется хореографией.
Вы захотите выбрать службу, которая будет отвечать за эту бизнес-логику. Этот сервис должен будет получать все предыдущие типы сообщений, чтобы он мог определить, когда (если) все они были выполнены, что он, вероятно, хочет сделать, записывая, какие из шлюзов уже прошли в базе данных.
Одна из альтернатив, которую вы могли бы рассмотреть, — это объединение бизнес-процессов в цепочку вместо их параллельного выполнения. Так...
- PAYBILL заставляет FinanceService дебетовать бухгалтерскую книгу и запускать «PaymentPosted»
- «PayentPosted» заставляет EmailService отправлять электронное письмо клиенту с благодарностью за оплату счета и транслирует «CustomerPaymentEmailSent»
- «CustomerPaymentEmailSent» заставляет DicsountService проверять, получают ли они скидку за своевременную оплату, а затем отправляет «CustomerCanGetPaymentDiscount».
- Электронное письмо, которое вы хотите отправить, просто инициируется «CustomerCanGetPaymentDiscount».
Если честно, я бы поменял модель зависимости, которую вы используете на этом последнем этапе. Таким образом, вместо того, чтобы какой-либо компонент прослушивал события «CustomerCanGetPaymentDiscount» от DiscountService и отправлял электронное письмо, я думаю, что вместо этого DiscountService сказал бы другому компоненту отправить электронное письмо. Мне кажется естественным, что что-то, что рассчитывает скидки, знает, что нужно отправить электронное письмо. Для того, кто отправляет электронные письма, кажется менее естественным знать о скидках (и обо всем остальном, что требует отправки электронных писем). Вот почему мне не нравятся архитектуры, в которых предполагается, что каждое сообщение должно быть событием, а каждое действие должно запускаться событием: это устраняет множество решений о том, где может жить логика предметной области, потому что получатель сообщения всегда должен знать о домене отправителя сообщения, а не наоборот.
Похожие вопросы
Новые вопросы
microservices
Архитектурный подход к разработке отдельного приложения в виде набора небольших отдельно развертываемых служб.