Потребитель шаблона Microservices Saga ожидает ответа

Я хотел бы уточнить, как лучше организовать архитектуру.

У меня есть остальные API и архитектура микросервисов. Я применил шаблон базы данных на службу.

Итак, давайте представим, что пользователь хочет создать заказ (система электронной коммерции). Но у пользователей может быть кредитный лимит. Таким образом, поток будет следующим:

  • OrderService создает отложенный ордер. Затем нажмите событие об этом.

  • UserService обрабатывает это событие и публикует либо событие превышения кредитного лимита, либо событие зарезервированного кредита.

  • OrderService получает событие и изменяет состояние заказа на утвержденное или отмененное.

Все хорошо выглядят. Но вопрос в том, что пользователь будет делать во время этого простого потока? Я имею в виду: пользователь делает POST-запрос/заказывает и...

  1. Веб-сервис ждет, пока заказ будет одобрен или отменен (включая, конечно, тайм-аут)?
  2. Веб-сервис возвращает 200 ok, и тогда пользователю нужно проверять состояние заказа с некоторым интервалом?
  3. использовать веб-сокеты?
  4. что-то другое?

К сожалению, у любого варианта из вышеперечисленных есть свои преимущества и свои недостатки.

Сложность в том, что я описал простейший случай. В реальности могут быть задействованы десятки сервисов (даже сторонних). И, конечно же, я рассчитываю на высокую нагрузку. Так что очередь может быть заполнена.

Пожалуйста, предложите решение для обсуждения. Я очень признателен за ответ, а также за ссылки на готовую системную документацию.


person David Markwell    schedule 13.07.2019    source источник
comment
Привет ~ Дэвид, это было давно для этого вопроса, у тебя есть какие-нибудь идеи по этому вопросу?   -  person cYee    schedule 01.06.2021


Ответы (3)


Спасибо за хороший вопрос. Если мы посмотрим на Saga Pattern, он предлагает выполнять ACID-подобные транзакции в распределенной системе, но с некоторым компромиссом. Одним из компромиссов является обеспечение отката, если какой-либо сервис или объект не выполняет то, что должен был делать. Это может стать еще более сложным, если у вас есть более 5 сервисов, завершающих сагу. Хотя это будет вариант с высокой масштабируемостью, если вы сможете организовать.

Здесь я предложу Следующее,

  • Пользователь делает POST-запрос для заказа
  • OrderService сначала проверяет с UserService относительно кредитного лимита (это может быть вызов REST API, так как это может быть простой вызов БД для UserService)
  • Затем OrderService может действовать на основе обратного ответа от UserService.

Преимущества этого подхода

  • Пользователь может увидеть немедленный ответ
  • Менее сложный код, поэтому его можно тестировать и поддерживать.

Недостатки этого подхода

  • Это решение не будет эффективным, если слишком много внешних (сторонних) вызовов rest API.
  • Это может ввести единую точку отказа

Главное, все варианты будут иметь компромиссы. Вам решать, какой из них подходит вам лучше всего.

person Zamiul Hasan    schedule 14.07.2019

по мне

Следуйте моему правилу: Сначала проверить, а потом действовать

Подтвердите заказ, прежде чем он перейдет к заказу услуги в пользовательском интерфейсе. Вы можете вызвать API-интерфейс userservice в пользовательском интерфейсе, который дает информацию, может ли пользователь сделать заказ или нет.

Шаг 1. В пользовательском интерфейсе вызовите API пользовательской службы, который проверяет кредитный лимит пользователя.

Шаг 2. Если проверка прошла успешно или неудачно

Шаг 3. Примите меры в соответствии с результатом шага 2. В случае успеха позвоните в службу заказа, если не сделаете то, что хотите (позвоните в другую службу и т. д.)

Преимущество

  1. Хороший пользовательский интерфейс. Пользователь получает подтверждающее сообщение «Вы не можете сделать заказ, ваш лимит низкий» или что-то в этом роде при попытке сделать заказ. Не в конце получить сообщение «У вас низкий лимит/или что-то еще»

  2. Меньшая сложность кода

  3. Более микросервисная арх.

Поскольку вы следуете за микросервисами, то, если вы вызываете пользовательский сервис внутри сервиса заказа, это означает, что сервис заказа зависит от него, или вы можете сказать, что он тесно связан - здесь вы теряете преимущество арки микросервиса.

Что произойдет, если пользовательский сервис не работает. Клиент не может сделать заказ, или если вы измените что-либо в ответе службы пользователя, вам также придется изменить службу заказа.

Что делать, если в будущем потребуется дополнительная проверка (для вызова другой службы) перед оформлением заказа.

  1. Гибкость перенаправления. Предположим, что при сбое проверки пользовательской службы вам придется вызывать другую службу (другую независимую микрослужбу), и если вы используете другую службу внутри службы заказов, количество услуг увеличивается по мере роста проекта.

  2. Меньше запросов к OrderService. Запрос отправляется в службу заказов только тогда, когда проверка проходит от другой службы или другого объекта.

Так что с моей точки зрения

  1. Постарайтесь сделать микросервис максимально независимым.

  2. Подтвердите сначала и действие.

  3. Хороший пользовательский опыт

  4. Легко справиться с нагрузкой (если вы думаете)

При всем при этом, теперь вы меньше зависите от саги.

Это только мое мнение - выбирайте то, что считаете лучшим в соответствии с вашим доменом.

person Ashwani Tiwari    schedule 14.07.2019
comment
Есть путаница, спрашивайте в комментариях - person Ashwani Tiwari; 14.07.2019
comment
Я полностью согласен с проверкой на стороне клиента для лучшего взаимодействия с пользователем. Спасибо. Но orderservices вообще не зависит от userservice. Он просто отправляет событие и подписывается и ждет, когда кредит зарезервирован или превышен кредитный лимит. - person David Markwell; 15.07.2019

Вопрос в том, что пользователь будет делать во время этого простого потока? Я имею в виду: пользователь делает POST-запрос/заказывает и...

Вы можете ответить пользователю на созданный идентификатор заказа со статусом «ожидание», пока ваша сага работает. Запрос должен заканчиваться на 200.

Как пользователь получает статус?

Push-уведомление, веб-сокет, электронная почта, смс. вы должны уведомить пользователя о статусе события, успехе, неудаче, ожидании_для_утверждения.

1. Web-service awaits until the order gets approved or canceled?
2. Web-service returns 200 ok and the user check the order state with some interval?
3. use web sockets?
4. something else?
  1. Не рекомендуется. Сага должна быть асинхронной. Ожидание ответа является синхронным (стиль запрос/ответ).
  2. Это будет работать, но если ваша сага длится долго, это может быть проблематично, например: что-либо с проверкой/одобрением человеком.
  3. Это будет работать, если вы отвечаете 200 после создания заказа в состоянии ожидания, во-первых, вы должны убедиться, что ваш веб-сокет активен, иначе вам все равно придется уведомить их по электронной почте, смс.

К сожалению, у любого варианта из вышеперечисленных есть свои преимущества и свои недостатки.

Вы должны выбрать свой яд.

Сложность в том, что я описал простейший случай. В реальности могут быть задействованы десятки сервисов (даже сторонних). И, конечно же, я рассчитываю на высокую нагрузку. Так что очередь может быть заполнена.

Используйте организованную сагу (типа) Netflix conductor, Uber Cadence, Temporal (аналогично к Каденс). Это позволит вам сделать что-то, как показано ниже. По крайней мере, легче.

Блок-схема от google shopping api и то, как они с этим справляются. введите здесь описание изображения

Ссылка для получения дополнительной информации: https://developers.google.com/shopping-content/guides/about-orders

person cYee    schedule 13.07.2021