Skip to content

Demo of using MassTransit for distibuted applications creation.

License

Notifications You must be signed in to change notification settings

qoollo/masstransit-demo

Repository files navigation

MassTransit Advanced Example

Техническое описание

Данный проект представляет собой демо-версию микросервисной архитектуры с оркестрацией и ипользованием service bus. В качестве реализации service bus был взят фреймворк MassTransit.

Суть проекта

Приложение представляет собой сервер для обработки клиентских заказов. Обработка заказаов состоит из следующих действий:

  • Подтверждение заказа
  • Резервация денег на карте клиента
  • Подтверждение/отклонение заказа менеджером
  • Доставка заказа
  • Получение обратной связи от клиента
  • Архивация заказа(записать всю сущность в базу данных)

Допущения

  • После подтверждения заказа пользователь не может сделать новый заказ или изменить текущую корзину, пока предыдущий не пройдет все стадии(его сага должна завершиться)

Схема микросервисов

![Microservice Diagram](/ReadmeFiles/Microservice Diagram.png)

Миросервисы

API service

Бизнес логика

  • API для пользователя и менеджера
  • Консьюмеры, которые обрабатывают события о заказе (в данном проекте эти события просто выводятся на консоль, но в реальном проекте скорее всего будет отправляться уведомления по веб-сокетам)

Consumers

  • NewOrderConfirmationRequestedConsumer: обрабатывает сообщения о том, что кто-то из менеджеров должен подтвердить заказ
  • OrderRejectedConsumer: обрабатывает сообщения о том, что заказ был отклонен менеджером
  • FeedbackRequestedConsumer: обрабатывает сообщения о том, что был запрос на обратную связь от клиента
  • GetArchievedOrderResponseConsumer: обрабатывает сообщения о том, что запрос на получение архированного заказа был обработан и пришло сообщение с данными о заказе

Cart service

Бизнес логика

  • Добавления/удаления товаров из корзины (данные хранятся в бд)
  • Обработка запроса на получение актуальной корзины

Особенности

  • Если в базе уже содержится добавляемый товар, то цена товара берется из базы. Если подобного товара в базе нет, то цена товара рандомится(чобы не услонять API)

Consumers

  • AddCartPositionConsumer: добавляет товар к заказу
  • RemoveCartPositionConsumer: убирает товар из заказа
  • GetCartConsumer: возвращает запрашиваемую корзину

Delivery service

Бизнес логика

  • Имитация пролонгированной во времени операции - доставки заказа

Consumers

  • DeliveryOrderConsumer: имитирует доставку заказа

Feedback service

Бизнес логика

  • Добавление отзывов пользователей (данные хранятся в бд)
  • Отправка сохранённых отзывов по запросу

Consumers

  • AddFeedbackConsumer: добавляет отзыв пользователя
  • GetOrderFeedbackConsumer: возвращает запрашиваемый отзыв по конкретному заказу

Payment service

Бизнес логика

  • Резервирует указанную сумму
  • Отменяет резервацию указанной суммы

Особенности

  • Данный сервис максимально "тупой", он прост логирует отправляемые ему команды и все

Consumers

  • ReserveMoneyConsumer: резервирует необходимую сумму
  • UnreserveMoneyConsumer: отменяет резервацию необходимой суммы

History service

Бизнес логика

  • Сохранение финализированных саг (данные хранятся в бд)
  • Отправка сохранённых отзывов по запросу

Consumers

  • ArchivedOrderConsumer: сохраняет сагу
  • GetOrderFromArchiveConsumer: возвращает информацию о завершённой саге

Оркестратор

Техническое описание

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

Саги

OrderStateMachine

Данная сага описывает жизненный цикл заказа. Данная сага хранится персистентно с использованием EntityFrameworkCore.

Реагирует на события:

  • OrderSubmitted
  • OrderConfirmed
  • OrderRejected
  • OrderDelivered
  • ReceivedFeedback
  • OrderAborted

Workflow schema

Saga workflow

[SagaWorkflow](ReadmeFiles/Saga Workflow Diagram.png)

ArchievedOrderStateMachine

Агрегирующая сага. Данная сага обращается к трем микросервисам(CartService, HistoryService, FeedbackService) для получения заархивированного заказа. Вполне стандартный кейс для использования стейт машины. Данные собираются паралелльно с помощью композит ивентов.

Подводные камни данной саги:

  • Не умеет работать в паре с IRequestClient, из-за чего необходимо сохранять RequestId и ResponseAddress в инстансе

Консьюмеры

  • GetOrderStateConsumer: получить состояние заказа по Id
  • GetAllOrdersStateConsumer: получить состояние всех заказов
  • GetArchivedOrderConsumer: получить заархивированный заказ (альтернатива ArchievedOrderStateMachine).

Инструкция по деплою

  1. Запусть build.sh в корневой директории проекта. (Данный скрипт собирает докер образы всех сервисов и создаёт файлы конфигов)
  2. docker-compose up

Эндпоинты

  • Swagger UI: 127.0.0.1:80/swagger
  • RabbitMQ: 127.0.0.1:15672 (guest/guest)
  • Prometeus: 127.0.0.1:9090
  • Grafana: 127.0.0.1:3000 (admin/admin)

Подводные камни

  • NRT плохо работает внутри стейт машины из-за ее декларативности, читаемость падает. Мы отключили фичу в файле со стейт машиной и инстансом
  • В персистентных (а лучше во всех) сагах нужно использовать outbox, чтобы сага сначала транзитилась в нужный стейт, а потом уже отправляла сообщения
  • При проверке одноного инстанса в юнит тестах на разные стейты с помощью метода Exists оба исхода могут оказатся положительными, так как метод awaitable
  • Инциализаторы в стейт машинах не могут прокидывать хедеры через двойное подчеркивание

About

Demo of using MassTransit for distibuted applications creation.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published