Проект релизован в качестве демонстрации работы микросервисов, контейнеров docker, брокера сообщений RabbitMQ. Схема взаимодействия микросервисов в проекте.
Порты, на которых располагаются микросервисы:
Возможности клиента:
Микросервис Factories в свою очередь каждые 20 секунд пополняет "склады" магазинов. А микросервис Shops при покупке клиентом товаров добавляет покупку в список покупок пользователя на микросервисе Purchases.
Каждый микросервис выполняет определённую роль. Рассмотрим их отдельно.
В каждом из микросервисов, кроме Factories используется swagger. В URL, прикреплённом к микросервисам вы сможете найти информацию по API-путям, а также методам, которые используются в данном микросервисе.
Каждый микросервис делится на 3 слоя :
Данный микросервис выполняет функцию аутентификации пользователей. Использует библиотеку AspNetCore.Identity для шифрования данных юзеров в БД, в частности использование хэшей, вместо паролей.
В ответ на логин пользователя, сервис шлёт токен JWT, в котором зашифрована информация по юзеру.
{
"succeeded": true,
"code": 200,
"result": {
"id": "ad6fbc79-71bc-4391-a673-c5784703eae8",
"userName": "User",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImFkNmZiYzc5LTcxYmMtNDM5MS1hNjczLWM1Nzg0NzAzZWFlOCIsIm5iZiI6MTYxNTA0ODU3MiwiZXhwIjoxNjE1NjUzMzcyLCJpYXQiOjE2MTUwNDg1NzJ9.FHvSD7-1T1104IP5Fjb9VbSf7xUyt90oGvinq8NEGhM"
},
"errors": []
}
В дальнейшем этот токен будет использоваться в заголовках запроса пользователя по другим микросервисам также.
Конкретнее, его нужно положить в заголовок Authorization - Bearer {yourToken}
.
Здесь пользователь может найти информацию по своим покупкам, а также сделать свои, но с ограничениями. Также пользователь может отредактировать покупки. Детальнее рассмотрим ниже.
Добавление
Если магазин добавляет покупку, то здесь, естественно, никаких ограничений нет. Если же пользователь, в таком случае он не может прикрепить к покупке чек, то есть
"receipt":null
актуально для покупок, созданных пользователем.
У покупок, созданных пользователем, параметр IsShopCreate
всегда false.
Пример тела запроса добавления своей покупки
{
"products": [
{
"name": "string",
"productId": 0,
"cost": 0,
"count": 0,
"category": "string"
}
],
"date": "2021-03-06T16:58:38.251Z",
"transactionType": 0
}
Без параметра date
или transactionType
также будет работать.
Редактирование
Пользователь может редактировать способ оплаты, параметр TransactionType
, значение 0 - оплата картой, 1 - наличными.
{
"id": 1,
"products": [
{
"name": "string",
"productId": 0,
"cost": 0,
"count": 0,
"category": "string"
}
],
"transactionType": 1
}
Здесь id
обязательно должен существовать, все заполняемые параметры в запросе будут изменены в покупке!
Ненужные параметры необходимо удалить.
Данный микросервис реализует логику взаимодействия пользователя с магазинами. Пользователь может посмотреть список магазинов, посмотреть товары в магазине, и купить список товаров в определенном магазине. Рассмотрим только последний пункт.
Покупка товаров пользователем
Каждый пользователь может купить товары, которые есть в магазине (не больше количества, что есть).
Пример тела запроса на покупку:
[
{
"productId": 0,
"count": 0,
}
]
Для запроса необходимо лишь два параметра : количество товара и Id товара. Если запрос на сервер будет отправлен валидный, и он будет успешным, в таком случае Shops
отправляет на сервис Purchases для этого пользователя новую покупку, в которой обязательно будет receipt
- чек.
{
"categoryName": "одежда"
}
categoryName
единственный и обязательный параметр.
Данный микросервис выполняет одну функцию - пополнения магазины товарами. Каждые 20 секунд данный сервис отправляет новые товары на сервис Shops, согласно данным в БД.
В проекте используется 4 базы данных:
Для микросервиса Factories:
Подход проектирования БД: Code first
Тип хранения данных: SQL Server & Docker
ORM: Entity Framework Core
занимает порты 15672 и 5672
В данном проекте RabbitMQ используется в связке с библиотекой MassTransit для обработки запросов с различных микросервисов. Каждый запрос попадает в Queue и обрабатывается после того, как достигает его очередь. Также RabbitMQ позволяет не терять запросы и взаимодействовать микросервисам друг с другом.
В каждом проекте в Startap'e прописаны конфигурации для соответсвующих очередей этому микросервису, которые работают с помощью библиотеки MassTransit.
Ниже пример добавления обработчиков (Consumer'ов) для очередей RabbitMQ,
// Identity
x.AddConsumer<Authenticate>();
x.AddConsumer<CreateUser>();
x.AddConsumer<GetUserByToken>();
и конфигурируются сами очереди
cfg.ReceiveEndpoint("identityQueue", e =>
{
e.PrefetchCount = 20;
e.UseMessageRetry(r => r.Interval(2, 100));
//// Identity
e.Consumer<Authenticate>(context);
e.Consumer<CreateUser>(context);
e.Consumer<GetUserByToken>(context);
});
Ниже можно найти настройки для сериализации/десериализации запросов. Используется Newtonsoft.Json.
cfg.ConfigureJsonSerializer(settings =>
{
settings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
return settings;
});
cfg.ConfigureJsonDeserializer(configure =>
{
configure.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
return configure;
});
Также в каждом микросервисе есть конфигурации для подключения к RabbitMQ :
services.AddMassTransit(x =>
{
x.UsingRabbitMq((context, cfg) =>
{
cfg.Host(new Uri("rabbitmq://host.docker.internal/"));
cfg.ConfigureJsonSerializer(settings =>
{
settings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
return settings;
});
cfg.ConfigureJsonDeserializer(configure =>
{
configure.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
return configure;
});
});
});
services.AddMassTransitHostedService();
API Gateway — это высокопроизводительный, доступный и безопасный сервис размещения API, который помогает создавать, разворачивать программные интерфейсы приложения в любом масштабе и управлять ими.
В данном проекте вы найдёте реализацию Ocelot Api Gateway
Для конфигурирования проекта подключается ocelot.json
файл, в котором расписаны пути, а также методы переадресации.
Документацию по нему вы сможете найти здесь
Данный проект поддерживает docker. Для его запуска достаточно прописать:
docker-compose pull
docker-compose up
Детали конфигурации docker-compose вы можете найти здесь.
В проекте есть Smoke - тесты, для запуска которых необходимо запустить менеджера RabbitMQ.
Они покрывают доступность функционала.
Также есть Unit - тесты, которые покрывают функционал сервисов Purchases и Shops.