Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
konvovden committed Dec 21, 2021
1 parent 2b1629d commit 9de8921
Show file tree
Hide file tree
Showing 213 changed files with 9,134 additions and 2 deletions.
42 changes: 42 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ mono_crash.*
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
Expand Down Expand Up @@ -61,6 +62,9 @@ project.lock.json
project.fragment.lock.json
artifacts/

# ASP.NET Scaffolding
ScaffoldingReadMe.txt

# StyleCop
StyleCopReport.xml

Expand All @@ -86,6 +90,7 @@ StyleCopReport.xml
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
Expand Down Expand Up @@ -137,6 +142,11 @@ _TeamCity*
.axoCover/*
!.axoCover/settings.json

# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info

# Visual Studio code coverage results
*.coverage
*.coveragexml
Expand Down Expand Up @@ -196,6 +206,9 @@ PublishScripts/
*.nuget.props
*.nuget.targets

# Nuget personal access tokens and Credentials
# nuget.config

# Microsoft Azure Build Output
csx/
*.build.csdef
Expand Down Expand Up @@ -348,3 +361,32 @@ MigrationBackup/

# Ionide (cross platform F# VS Code tools) working folder
.ionide/

# Fody - auto-generated XML schema
FodyWeavers.xsd

# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace

# Local History for Visual Studio Code
.history/

# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp

# JetBrains Rider
.idea/
*.sln.iml

# Project data
data/
appsettings/
157 changes: 155 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,155 @@
# masstransit-demo
Demo of using MassTransit for distibuted applications creation.
# 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](/ReadmeFiles/saga_workflow.png)

[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
+ Инциализаторы в стейт машинах не могут прокидывать хедеры через двойное подчеркивание
Empty file added ReadmeFiles/.gitkeep
Empty file.
Binary file added ReadmeFiles/Microservice Diagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ReadmeFiles/Saga Workflow Diagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ReadmeFiles/saga_workflow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
dotnet publish src/MassTransitAdvancedExample.sln -c Release

mkdir -p appsettings

chmod +x ./scripts/wait-for-it.sh
chmod +x ./scripts/buildservice.sh

./scripts/buildservice.sh api_service ApiService
./scripts/buildservice.sh cart_service CartService
./scripts/buildservice.sh delivery_service DeliveryService
./scripts/buildservice.sh feedback_service FeedbackService
./scripts/buildservice.sh history_service HistoryService
./scripts/buildservice.sh orchestrator_service OrderOrchestratorService
./scripts/buildservice.sh payment_service PaymentService
10 changes: 10 additions & 0 deletions configs/grafana/dashboards.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: 1

providers:
- name: 'rabbitmq'
orgId: 1
folder: ''
type: file
disableDeletion: true
options:
path: /dashboards
Loading

0 comments on commit 9de8921

Please sign in to comment.