Связь в архитектуре микросервисов - PullRequest
0 голосов
/ 01 июля 2018

При работе над приложением в архитектуре микросервисов я столкнулся с проблемами, связанными между сервисами.

Это типичное приложение для заказа товаров. Разумно иметь сервис, который будет работать как каталог продукции. Наш клиент JavaScript может запросить эту услугу для доступных продуктов и показать их в браузере. Когда пользователь нажимает на товар, мы должны создать заказ. Мы хотели бы управлять заказами в другом сервисе. Итак, заказ создан - это означает, что пользователь X заказал продукт Y. На техническом уровне мы просто сохраняем идентификатор пользователя и идентификатор продукта в базе данных.

Подводя итог, мы имеем:

Сервис продуктов

Класс продукта:
Код продукта, название продукта

Служба заказов

Класс заказа:
Идентификатор заказа, идентификатор продукта, идентификатор пользователя, дата заказа

Теперь давайте представим следующий сценарий - в клиенте JavaScript мы хотели бы перечислить все товары, которые заказал пользователь. Сервис заказов предоставляет список идентификаторов продуктов для данного пользователя. Но пользователю важно имя продукта, а не его идентификатор. К сожалению, служба заказов ничего не знает о названиях продуктов.

Мы могли бы решить эту проблему несколькими способами:

  • Просто предположите, что клиент несет ответственность за получение необходимой ему информации. Поэтому после вызова службы заказов и получения списка идентификаторов продуктов она выполняет еще один вызов службы продуктов, передавая идентификаторы продуктов и получая соответствующие названия продуктов в ответ. Затем клиент собирает оба ответа во что-то полезное. Такой подход обеспечивает чистоту наших услуг без утечки знаний о предметной области от одного сервиса к другому. Но это требует больше работы на стороне клиента.

  • Служба заказов на запрос о заказанных товарах звонит на бэкэнд в службу товаров. Он извлекает названия продуктов, собирает ответ, содержащий orderDate и productName, и отправляет его клиенту. Все, что остается сделать клиенту - это представить данные. Недостатком этого подхода является то, что сервис заказов теперь получает больше знаний о продуктах, чем необходимый.

  • Дублирующая информация о названии товара в сервисе заказов. При создании заказа мы передаем не только идентификатор продукта, но и название продукта. Это означает, что класс Order будет выглядеть так: Класс заказа:
    Идентификатор заказа, идентификатор продукта, название продукта, идентификатор пользователя, дата заказа
    Теперь мы можем легко предоставить полную информацию о заказе без дополнительного звонка в сервис «Продукты». Также на этот раз служба заказов имеет слишком много знаний о продуктах. Что выгодно, так это то, что служба заказов может предоставлять релевантные данные, даже если служба продуктов не работает.

Может ли любой из этих подходов считаться наилучшей практикой? Или есть разные решения?

1 Ответ

0 голосов
/ 01 июля 2018

В примере eShopOnContainers (https://github.com/dotnet-architecture/eShopOnContainers) они добавляют следующие поля при создании позиции заказа:

        public void AddOrderItem(int productId, string productName, decimal unitPrice, decimal discount, string pictureUrl, int units = 1)

Это дублирует информацию каталога, однако, поскольку это моментальный снимок записи. Это гораздо безопаснее, чем ссылки на исходные данные.

На этом этапе пользовательского пути вы находитесь в домене заказа, если пользователь просматривает заказ, вы можете указать ссылку на каталог. Однако служба заказа должна иметь возможность работать самостоятельно. Ссылка на каталог для получения информации о продуктах не позволяет службе заказа владеть собственными данными.

Кошмарный сценарий, когда цена меняется в каталоге ... Что будет с историческими заказами?

...