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

Для этого мы будем использовать Net core 2.2, Dapper для связи с базой данных и Docker для размещения наших микросервисов на каждой платформе, которую мы хотим. Мы будем использовать RabbitMQ для связи между нашей электронной почтой и пользовательским API, используя библиотеку MassTransit, доступную в ядре Net.

Исходники проекта доступны здесь:



Структура проекта

Первое, что нужно сделать, это создать структуру приложения. Будет четыре проекта; основной проект, реализующий службы, инфраструктура, реализующая репозитории, а также проект API пользователя и электронной почты.

Давайте создадим нашу папку и проекты:

mkdir microservices
cd microservices
mkdir services
cd services

Итак, у нас есть готовые папки, теперь давайте создадим наш проект net core:

dotnet new webapi -o user
dotnet new webapi -o email
dotnet new classlib -o core
dotnet new classlib -o infrastructure

Докер

Теперь, когда у нас готовы наши проекты и папки, мы начинаем создавать наш Dockerfile, пользовательский интерфейс и API электронной почты имеют свой собственный Dockerfile, который позволяет нам внедрять все необходимые нам зависимости, а в корне проекта будет файл docker-compose. файл:

Файл docker-compose загрузит все необходимые зависимости и образы, SQL Server с файлами инициализации, RabbitMQ будет взаимодействовать между микросервисами и двумя нашими API. Хорошая вещь с Docker заключается в том, что вы можете использовать SQL Server в качестве базы данных в ОС unix.

Вот Dockerfile пользовательского API, куда мы можем загрузить все зависимости проекта. Я назвал его пользователем Dockerfile и поместил в служебную папку. Каждый файл api Dockerfile находится в служебной папке и имеет следующее имя [имя проекта] .Dockerfile:

После настройки Docker вы можете собрать контейнер и проверить, все ли в порядке. Для этого перейдите в корневой каталог и выполните эту команду:

docker-compose up --build

Это запустит docker compose и соберет ваш проект, а затем он разместит каждый ваш проект в одном контейнере.
Наконец, вы можете перейти к http: // localhost: 8081 / api / values, тогда вы должны см. начальную страницу по умолчанию API ядра сети.

Репозиторий

Теперь давайте запрограммируем некоторые службы и репозитории для взаимодействия с базой данных. В основном проекте давайте создадим простой репозиторий IUserRepository. Как только это будет сделано, мы реализуем этот интерфейс в инфраструктурном проекте. У нас есть всего два простых метода; один, который получает всех пользователей в базе данных, и другой, который добавляет нового пользователя:

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

IDbProvider - это интерфейс, который обеспечивает соединение, необходимое для запроса базы данных. Я создал для этого интерфейс, поэтому код находится в одном месте, и я могу использовать мощную инъекцию зависимостей ядра Net, чтобы использовать его во всем моем репозитории. Вы можете найти его определение на github.

Контроллер

После создания репозиториев мы используем наш репозиторий внутри нашей UserService и будем обслуживать UsersController вместе со службой. Внутри UsersController мы попросим RabbitMQ сообщить службе электронной почты, что нужно отправить электронное письмо новому пользователю.

Вот реализация UsersController:

Как мы видим, интересный материал присутствует в методе Post, давайте объясним, что происходит в этих трех строках:

Uri uri = new Uri($"rabbitmq://{_config.GetValue<string>("RabbitMQHostName")}/create_user");
var endPoint = await _bus.GetSendEndpoint(uri);            
await endPoint.Send(res);
  • В первой строке мы получаем uri шины, на которую мы хотим отправить наше сообщение, в нашем случае мы хотим отправить его на / create_user
  • Вторая строка получает точку отправки, куда мы будем отправлять наше сообщение.
  • И последнее, но не менее важное: мы отправляем наше сообщение в RabbitMQ.

После отправки сообщения все получатели, которые подписались на / create_user, получат сообщение и смогут его использовать. В нашем случае это API электронной почты, который получит сообщение и отправит электронное письмо.

Чтобы он заработал, нам нужно настроить соединение с RabbitMQ, для этого мы воспользуемся MassTransit.

Общественный транспорт

В файле startup.cs пользовательского api мы добавим эти строки в метод ConfigureServices:

Здесь мы настраиваем MassTransit для связи с RabbitMQ, мы передаем URL-адрес RabbitMQ в MassTransit и предоставляем имя пользователя и пароль для подключения. В этом примере мы используем учетные данные по умолчанию. После завершения настройки нам нужно запустить соединение, что мы и сделаем в методе Configure. Вам нужно добавить к функции параметр IApplicationLifetime, а затем добавить следующие строки в конце метода:

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

Теперь, если вы запустите докер, вы сможете отправить запрос на обмен create_user в RabbitMQ. Теперь нам нужно реализовать конечную точку получателя.
Перейдем к API электронной почты.

Получатель

Чтобы получить наше сообщение, нам нужно подписаться на обмен create_user. Для этого в MassTransit нам нужно использовать потребителя, который представляет собой класс с методом Consume, который будет вызываться каждый раз при получении сообщения.

У нашего потребителя могут быть некоторые зависимости, ядро ​​Net разрешит их с помощью внедрения зависимостей.

Сначала давайте настроим MassTransit в файле запуска электронной почты, мы добавим эти строки в ConfigurationServices:

Некоторые пояснения:

  • В первой строке мы регистрируем нашего потребителя для внедрения зависимостей, ему нужен IEmailService
  • Затем мы создаем соединение с RabbitMQ и даем учетные данные
  • Наконец, мы создаем конечную точку нашего получателя. Важная часть - последняя, ​​где мы настраиваем нашего потребителя. Эта строка указывает MassTransit использовать CreateUserConsumer для использования нашего сообщения.

Теперь нам нужно запустить подключение к шине так же, как в пользовательском api.

Потребитель

Давайте посмотрим на потребительский класс:

У нас есть очень простой потребитель, у которого только что появился новый адрес электронной почты в базе данных. Как видите, нам нужно реализовать интерфейс IConsumer и сообщить ему модель, которую он получит. Это должен быть тот же класс, что и тот, который использовался для отправки сообщения. Если вы не используете один и тот же класс, все отправляемые вами сообщения попадут в очередь пропущенных, потому что они не будут распознаны.

Заключение

Теперь, если вы создадите свое приложение и запустите его в Docker, вы можете добавить пользователя с помощью простой команды curl:

curl --header "Content-Type: application/json" --request POST --data '{"Email": "[email protected]", "Password": "password"}' http://localhost:8081/api/users

А если вы перейдете на http: // localhost: 8082 / api / emails, вы увидите отправленное письмо.

Итак, как видите, очень легко обмениваться данными между микросервисами с помощью инструментов, доступных в ядре Net. К сожалению, мы не реализовали систему аутентификации, но мы увидим это в следующей публикации. Мы также рассмотрим, как удалить пользователя и все связанные с ним данные.

Вуаля!

Спасибо, что прочитали действительно длинный первый пост :)