MassTransit é um framework fantástico para comunicação assíncrona em aplicações distribuídas, tanto que a própria documentação cita:
MassTransit é uma estrutura de aplicação distribuída de código aberto para .NET que facilita a criação de aplicações e serviços que potencializam a comunicação assíncrona, baseada em mensagens e fracamente acoplada para maior disponibilidade, confiabilidade e escalabilidade.
Vantagens do MassTransit
- Código aberto e gratuito
- Fácil de configurar e utilizar
- Contém muitos padrões de mensagem de microservices (Retry, circuit braker)
- Tratamento de exceções integrado
- Transação distribuída (Saga, event-drive, roteamento)
- Agendamento de mensagens
- Monitoramento
A facilidade e a resiliência que o MassTransit nos oferece é absolutamente tudo o que precisamos saber.
Neste artigo, mas uma vez vamos direto ao ponto: Configurar uma API no .NET 6.0 com o cenário de envio de mensagens (publish) para um Worker Service que recebe (subscribe) e processa essas mensagens utilizando o MassTransit.
Pré-requisitos
- Visual Studio 2022 (.NET 6.0)
- Docker Compose com RabbitMQ
- Nuget package MassTransit.AspNetCore e MassTransit.RabbitMQ
API
O primeiro passo é configurar o docker-compose com a imagem do RabbitMQ (que é um dos message broker de código aberto mais populares). Basicamente, ele oferece à suas aplicações uma plataforma comum para enviar e receber mensagens, garantindo que os dados nunca sejam perdidos e recebidos com êxito pelos consumidores, além de oferecer suporte a vários protocolos de mensagens.
version: "3.8"
services:
rabbitmq:
image: masstransit/rabbitmq
ports:
- 5672:5672
- 15672:15672
Caso não queira utilizar o Docker, é possível utilizar o RabbitMQ em uma conta gratuita no CloudAMQP.
Em seguida é preciso configurar a classe Program da API:
Neste código temos a extensão AddMassTransit responsável por registrar o service bus do RabbitMQ, que está configurado no appsettings.json:
"ConnectionStrings": {
"RabbitMq": "amqp://guest:guest@localhost:5672"
}
Em seguida, precisamos configurar o envio de mensagens na ClientController:
O IPublishEndpoint é a interface genérica responsável pelo envio de mensagens. Independente do provedor escolhido (In Memory, RabbitMQ, Azure Service Bus, etc).
Worker Service
O Worker Service trabalha como uma aplicação executada em segundo plano, responsável apenas por consumir e processar mensagens. Esse tipo de aplicação é uma ótima escolha em ambientes distribuídos / microservices por ser extremamente leve e carregando apenas o necessário, facilitando na escala.
O próximo passo é configurar a classe Program do Worker Service:
A classe Bus (Bus.Factory) é responsável por configurar o consumo das mensagens do RabbitMQ, onde é necessário configurar o ReceiveEndpoint com o nome da queue (que pode ser qualquer nome, já que o envio e recebimento das mensagens pelo MassTransit é definido pelo nome do tipo de objeto, incluindo o namespace).
Outra configuração importante é o UseMessageRetry responsável pela resiliência nas tentativas em caso de erro. Neste exemplo foi configurado em 3 tentativas no intervalo de 100 milissegundos.
No código abaixo temos a definição do Consumer, chamado de WorkerClient:
Tanto na controller como no worker é utilizado o mesmo objeto (ClientModel) para o envio e recebimento.
Solução Completa
No final, a solução fica com essa estrutura:
- Sample.Masstransit.WebAPI: API responsável pelo envio de mensagens.
- Sample.Masstransit.Worker: Worker Service responsável pelo recebimento das mensagens.
- Sample.Masstransit.WebApi.Core: Abstrações genéricas utilizado pela API e Worker
Para realizar os testes é preciso configurar a solução com a inicialização simultânea do projeto WebApi e Worker e executar o comando docker-compose na pasta raiz do projeto:
docker-compose up
Testando a aplicação é possível ver o envio e recebimento de mensagens orquestrado MassTransit:
Finalizando, o MassTransit é sem dúvida a melhor abstração na utilização de message brokers, podendo ser utilizado em vários cenários, como por exemplo, em migrações de aplicações legadas para novas arquiteturas, onde é necessário manter várias bases de dados atualizadas, sendo necessário o envio de mensagens para topics em um bus para a sincronização das bases.
Os detalhes completo sobre a implementação do MassTransit no .NET 6.0 você encontra no meu GitHub:
https://github.com/hgmauri/sample-masstransit