Hoje vamos recordar como usar o RabbitMQ em uma aplicação Asp.NET Core Web API. |
Neste artigo, discutiremos o RabbitMQ Message Queue
e sua implementação usando uma aplicação ASP.NET Core Web API da plataforma .NET
como um produtor de mensagens e um aplicativo console como consumidor de mensagens.
O que é o RabbitMQ ?
O RabbitMQ é um sistema de mensagens de código aberto (open-source) que atua como um intermediário (broker) de mensagens em sistemas distribuídos. Ele implementa o protocolo de mensagens avançado chamado AMQP (Advanced Message Queuing Protocol) e facilita a comunicação entre diferentes componentes de software, distribuídos em redes ou em ambientes onde há a necessidade de trocar informações de forma assíncrona.
Assim podemos dizer que :
O RabbitMQ é o agente de mensagens que atua como um middleware ao usar vários microsserviços;
O RabbitMQ é um software agente de mensagens(broker) de código aberto;
O RabbitMQ é escrito na linguagem de programação Erlang;
O RabbitMQ é usado para reduzir o tempo de carregamento e entrega de um aplicativo Web quando alguns dos recursos levarão muito tempo para processar os dados;
Abaixo temos um diagrama que mostra de forma resumida como o RabbitMQ atua :
Como você pode
ver no diagrama acima, há um produtor que envia uma mensagem para o servidor
RabbitMQ. O servidor armazenará essa mensagem dentro da fila usando a
abordagem FIFO;
Depois que o produtor enviou a mensagem para a fila, pode haver vários consumidores que desejam que a mensagem seja produzida pelo produtor. Nesse caso, os consumidores assinam a mensagem e obtêm essa mensagem da fila de mensagens;
Existem vários microsserviços em execução em segundo plano enquanto usamos o site de comércio eletrônico. Existe um serviço que cuida dos detalhes do pedido e outro serviço que cuida dos detalhes de pagamento e recibos.
Suponha que fizemos um pedido. Nesse momento, o serviço de pedidos iniciará e
processará nosso pedido. Depois de obter os detalhes do pedido, ele enviará os
dados para o serviço de pagamento, que receberá o pagamento e enviará o
comprovante de pagamento aos usuários finais.
Nesse caso, pode haver a possibilidade de ocorrer algum problema técnico no
serviço de pagamento. Caso o usuário não tenha recebido o comprovante de
pagamento devido a isso, o usuário será impactado e conectado com a equipe de
suporte para tentar saber o status do pedido.
Pode haver outro cenário no lado do usuário (consumidor). Talvez devido a algum
problema técnico, o usuário sai do aplicativo quando o pagamento está em
andamento. Mas ele não receberá nenhum detalhe de recebimento após o pagamento
ser processado com sucesso pelos serviços de back-end.
Nesses cenários, o RabbitMQ desempenha um papel essencial para processar
mensagens na fila de mensagens. Assim, quando o consumidor estiver online, ele
receberá aquela mensagem de recebimento do pedido da fila de mensagens,
produzida pelo produtor sem impactar a aplicação web.
Todos esses exemplos são apenas para fins de compreensão. Existem muitos
cenários nos quais o RabbitMQ pode desempenhar um papel importante ao usar
vários microsserviços. Às vezes, o RabbitMQ é usado totalmente para
balanceamento de carga entre vários serviços ou para muitos outros propósitos.
Benefícios de usar RabbitMQ
Há muitos benefícios em usar um Message Broker para
enviar dados ao consumidor. A seguir, falaremos sobre alguns desses benefícios.
Alta Disponibilidade
Quando vários microsserviços são usados pelo aplicativo, se um dos
microsserviços for interrompido por motivos técnicos naquele momento, a mensagem
nunca será perdida. Em vez disso, ele persiste no servidor RabbitMQ. Depois de
algum tempo, quando nosso serviço começar a funcionar, ele se conectará ao
RabbitMQ e receberá a mensagem pendente facilmente.
Escalabilidade
Quando utilizamos o RabbitMQ, nesse momento nossa aplicação não depende de
apenas um servidor e máquina virtual para processar uma requisição. Se nosso
servidor estiver parado nesse momento, o RabbitMQ transferirá nossa carga de
aplicativo para outro servidor que tenha os mesmos serviços em execução em
segundo plano.
Como exemplo vamos criar um projeto Web API que vai ser o produtor de mensagens e a seguir vamos incluir um projeto do tipo Console que vai ser o consumidor das mensagens.
Recursos usados:
NET 6.0
VS 2022
SQL Server
RabbitMQ
EF Core
Docker
Criando o projeto Web API
Abra o VS 2022 Community e selecione a opção Create New Project;
Selecione o template ASP.NET Core Web API e informe o nome ApiRabbitMq;
A seguir defina as configurações conforme a figura abaixo e clique em Create;
Vamos incluir no projeto as referências aos seguintes pacotes:
Podemos fazer isso usando o comando : dotnet add package <nome-pacote> ou via menu Tools-> ...-> Manage Nuget Packages for Solution e na guia Browse selecionar os pacotes.
A seguir vamos criar no projeto as seguintes pastas:
Vamos iniciar criando a entidade Product que representa o nosso modelo de domínio na pasta Models:
public class Product { public int ProductID { get; set; } public string? Name { get; set; } public string? Descriptoin { get; set; } public int Stock { get; set; } } |
A seguir defina a string de conexão no arquivo appsettings.json:
{ "ConnectionStrings": { "DefaultConnection": "Data Source=SQLEXPRESS;Initial Catalog=RabitMQDB;Integrated Security=True" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" } |
Na pasta Context vamos criar o arquivo de contexto do EF Core -
AppDbContext - que herda de
DbContext e define o mapeamento ORM :
public class AppDbContext : DbContext { protected readonly IConfiguration Configuration; public AppDbContext(IConfiguration configuration) { Configuration = configuration; } protected override void OnConfiguring(DbContextOptionsBuilder options) public DbSet<Product> Products{get;set;}
|
Vamos criar na pasta Services a interface IProductService :
public interface IProductService { public IEnumerable<Product> GetProductList(); public Product GetProductById(int id); public Product AddProduct(Product product); public Product UpdateProduct(Product product); public bool DeleteProduct(int Id); } |
A seguir crie a classe ProductService
que implementa esta interface e que vai definir as operações a serem realizadas:
using ApiRabbitMq.Context; using ApiRabbitMq.Models; namespace ApiRabbitMq.Services; public class ProductService : IProductService |
Na pasta RabbitMQ vamos implementar o serviço do Message Broker para produzir mensagens. Crie a interface IRabbitMQProducer :
public interface IRabbitMQProducer { void SendProductMessage<T>(T message); } |
A seguir crie a classe RabbitMQProducer que implementa esta interface :
using RabbitMQ.Client; using System.Text; using System.Text.Json; namespace ApiRabbitMq.RabbitMQ; public class RabbitMQProducer : IRabbitMQProducer |
Agora vamos registrar os serviços na classe Program:
using ApiRabbitMq.Context; using ApiRabbitMq.RabbitMQ; using ApiRabbitMq.Services; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); //registra os serviços no container var app = builder.Build(); // Configure the HTTP request pipeline. app.UseHttpsRedirection(); |
Agora podemos aplicar o Migrations para criar o banco de dados RabitMQDB e a tabela Products no SQL Server :
dotnet ef migrations add Inicial
dotnet ef database update
Ao final podemos consulta a janela Server Explorer do VS
2022 e verificar o banco e a tabela criados:
Executando o projeto neste momente teremos na interface do Swagger os endpoints criados para nossa API:
Na próxima parte do artigo vou incluir a aplicação Console no projeto e enviar e receber mensagens usando o RabbitMQ.
"Mas se não
derdes ouvidos à voz do Senhor, e antes fordes rebeldes ao mandado do
Senhor, a mão do Senhor será contra vós, como o era contra vossos pais."
1 Samuel 12:15
Referências: