Exercício – Enviar mensagens entre microsserviços por meio do RabbitMQ
O RabbitMQ é um agente de mensagens confiável que fornece trocas de mensagens flexíveis e filas. Para enviar e receber mensagens por meio do RabbitMQ em um projeto do .NET Aspire, você deve adicionar um contêiner do RabbitMQ e, em seguida, criar um código que envia mensagens de um microsserviço e as recebe em outro.
Neste exercício, você enviará mensagens para uma fila do projeto Catalog.API. Você adicionará um novo projeto de serviço em segundo plano que recebe essas mensagens da fila e as envia para o log do console para exibição.
Instalar pré-requisitos
Os pré-requisitos para o .NET Aspire são:
- .NET 8
- Visual Studio 2022 Preview
- Docker Desktop ou Podman
- Carga de trabalho do .NET Aspire no Visual Studio
Se você já tiver esses pacotes instalados, poderá avançar para começar a trabalhar com o RabbitMQ.
Instalar o .NET 8
Siga esse link do .NET 8 e selecione o instalador correto para o seu sistema operacional. Por exemplo, se você estiver usando o Windows 11 e um processador moderno, selecione x64 .NET 8 SDK para Windows.
Após a conclusão do download, execute o instalador e siga as instruções. Em uma janela de terminal, execute o seguinte comando para verificar se a instalação foi bem-sucedida:
dotnet --version
Você deverá ver o número da versão do SDK do .NET instalado. Por exemplo:
8.0.300-preview.24203.14
Instale a versão prévia do Visual Studio 2022
Siga esse link Visual Studio 2022 Preview e selecione Baixar versão prévia. Após a conclusão do download, execute o instalador e siga as instruções.
Instalar o Docker Desktop
Siga esse link Docker Desktop e selecione o instalador correto para o seu sistema operacional. Após a conclusão do download, execute o instalador e siga as instruções. Para melhor desempenho e compatibilidade, use o backend WSL 2.
Abra o aplicativo Docker Desktop e aceite o contrato de serviço.
Instale a carga de trabalho do .NET Aspire no Visual Studio
Instale a carga de trabalho do .NET Aspire usando a CLI do .NET:
Abra um terminal.
Atualize as cargas de trabalho do .NET com esse comando:
dotnet workload update
Você deverá ver uma mensagem informando que as cargas de trabalho foram atualizadas com sucesso.
No workloads installed for this feature band. To update workloads installed with earlier SDK versions, include the --from-previous-sdk option. Updated advertising manifest microsoft.net.sdk.ios. Updated advertising manifest microsoft.net.workload.mono.toolchain.net6. Updated advertising manifest microsoft.net.sdk.android. Updated advertising manifest microsoft.net.workload.emscripten.net7. Updated advertising manifest microsoft.net.workload.emscripten.net6. Updated advertising manifest microsoft.net.sdk.macos. Updated advertising manifest microsoft.net.workload.emscripten.current. Updated advertising manifest microsoft.net.workload.mono.toolchain.current. Updated advertising manifest microsoft.net.sdk.maui. Updated advertising manifest microsoft.net.workload.mono.toolchain.net7. Updated advertising manifest microsoft.net.sdk.maccatalyst. Updated advertising manifest microsoft.net.sdk.tvos. Updated advertising manifest microsoft.net.sdk.aspire. No workloads installed for this feature band. To update workloads installed with earlier SDK versions, include the --from-previous-sdk option. Successfully updated workload(s): .
Instale a carga de trabalho do .NET Aspire com esse comando:
dotnet workload install aspire
Você verá uma mensagem informando que a carga de trabalho do Aspire foi instalada.
Installing Aspire.Hosting.Sdk.Msi.x64 ...... Done Installing Aspire.ProjectTemplates.Msi.x64 ..... Done Installing Aspire.Hosting.Orchestration.win-x64.Msi.x64 ............. Done Installing Aspire.Hosting.Msi.x64 ..... Done Installing Aspire.Dashboard.Sdk.win-x64.Msi.x64 ....... Done Successfully installed workload(s) aspire.
Verifique se a carga de trabalho do .NET Aspire está instalada com esse comando:
dotnet workload list
Você deverá ver os detalhes da carga de trabalho do .NET Aspire.
Installed Workload Id Manifest Version Installation Source --------------------------------------------------------------------------------------------- aspire 8.0.0/8.0.100 SDK 8.0.300-preview.24203, VS 17.10.34902.84 Use `dotnet workload search` to find additional workloads to install.
Clonar projeto
Vamos usar git
para obter um aplicativo de exemplo, que ainda não usa um agente de mensagens:
Na linha de comando, navegue até uma pasta de sua escolha onde você possa trabalhar com o código.
Execute o seguinte comando para clonar o aplicativo de exemplo:
git clone -b aspire-rabbitmq https://github.com/MicrosoftDocs/mslearn-aspire-starter
Criar o contêiner do RabbitMQ
Vamos começar adicionando o RabbitMQ ao projeto de host do aplicativo. Quando iniciamos a solução, o .NET Aspire adiciona um contêiner do RabbitMQ ao aplicativo e passa referências aos projetos que a usam:
Inicie o Visual Studio e selecione Abrir um projeto ou solução.
Navegue até a pasta em que você clonou o projeto.
Clique duas vezes na pasta start, selecione a solução eShop.rabbitmq.sln e, em seguida, selecione Abrir.
No Gerenciador de Soluções, clique com o botão direito do mouse no projeto eShop.AppHost, selecione Adicionar e, em seguida, selecione pacote .NET Aspire.
Na caixa de texto de pesquisa, no final do texto existente, digite RabbitMQ.
Selecione o pacote Aspire.Hosting.RabbitMQ.
Na lista Versão, selecione a versão 8.0.0 mais recente e selecione Instalar.
Se a caixa de diálogo Visualizar alterações aparecer, selecione Aplicar.
Na caixa de diálogo Aceitação da Licença, selecione Aceito.
No Gerenciador de Soluções, expanda o eShop.AppHost e clique duas vezes em Program.cs.
Localize a seguinte linha de código:
var builder = DistributedApplication.CreateBuilder(args);
Imediatamente após esse código, para registrar um servidor do RabbitMQ, adicione este código:
var messaging = builder.AddRabbitMQ("messaging");
Localize o código a seguir, que registra o projeto Catalog.API para orquestração do .NET Aspire:
var catalogApi = builder.AddProject<Catalog_API>("catalog-api") .WithReference(catalogDb);
Para passar o serviço do RabbitMQ para o projeto Catalog.API, altere o código para corresponder a este:
var catalogApi = builder.AddProject<Catalog_API>("catalog-api") .WithReference(catalogDb) .WithReference(messaging);
Adicionar o RabbitMQ ao projeto Catalog.API
Agora, podemos instalar e configurar o RabbitMQ no projeto Catalog.API:
No Visual Studio, no Gerenciador de Soluções, clique com o botão direito do mouse no projeto Catalog.API, selecione Adicionar e, em seguida, selecione o pacote .NET Aspire.
Na caixa de texto de pesquisa, no final do texto existente, digite RabbitMQ.
Selecione o pacote Aspire.RabbitMQ.Client.
Na lista Versão, selecione a versão 8.0.0 mais recente e selecione Instalar.
Se a caixa de diálogo Visualizar alterações aparecer, selecione Aplicar.
Na caixa de diálogo Aceitação da Licença, selecione Aceito.
No Gerenciador de Soluções, expanda o projeto Catalog.API e clique duas vezes no Program.cs.
No arquivo Program.cs, localize a seguinte linha de código:
var builder = WebApplication.CreateBuilder(args);
Imediatamente após essa linha, para registrar a conexão do RabbitMQ, adicione este código:
builder.AddRabbitMQClient("messaging");
Enviar uma mensagem para uma fila do RabbitMQ
Quando um usuário solicita os itens no catálogo, queremos enviar uma mensagem para uma fila do RabbitMQ que descreve os detalhes da solicitação. Vamos adicionar esse código agora:
No Gerenciador de Soluções expanda Catalog.API > Apis e clique duas vezes em CatalogApi.cs.
Localize o seguinte código, que declara o
GetAllItems()
método:public static async Task<Results<Ok<PaginatedItems<CatalogItem>>, BadRequest<string>>> GetAllItems( [AsParameters] PaginationRequest paginationRequest, [AsParameters] CatalogServices services) {
Para usar a injeção de dependência e obter a conexão com o RabbitMQ, modifique o código para corresponder às seguintes linhas:
public static async Task<Results<Ok<PaginatedItems<CatalogItem>>, BadRequest<string>>> GetAllItems( [AsParameters] PaginationRequest paginationRequest, [AsParameters] CatalogServices services, RabbitMQ.Client.IConnection connection) {
Localize a seguinte linha de código:
var totalItems = await services.DbContext.CatalogItems .LongCountAsync();
Imediatamente após essa linha, para criar um canal de mensagens do RabbitMQ, adicione este código:
var channel = connection.CreateModel();
Na próxima linha, para criar uma fila de mensagens, adicione este código:
channel.QueueDeclare(queue: "catalogEvents", durable: false, exclusive: false, autoDelete: false, arguments: null);
Na próxima linha, para enviar a mensagem, adicione este código:
var body = Encoding.UTF8.GetBytes("Getting all items in the catalog."); channel.BasicPublish(exchange: string.Empty, routingKey: "catalogEvents", mandatory: false, basicProperties: null, body: body);
Adicionar um projeto consumidor de mensagem
Para receber mensagens da fila do RabbitMQ, vamos criar um projeto:
No Gerenciador de Soluções, clique com o botão direito do mouse na solução, aponte para Adicionar e selecione Novo Projeto.
Na caixa de texto Pesquisar modelos, digite Console.
Selecione o modelo do Aplicativo de Console do C# e selecione Avançar.
Na caixa de texto Nome do projeto, digite RabbitConsumer e selecione Avançar.
Na lista do Framework, verifique se o .NET 8.0 está selecionado e selecione Criar.
No Gerenciador de Soluções, clique com o botão direito do mouse no projeto AppHost, aponte para Adicionar e selecione Referência do Projeto.
Na lista de projetos, verifique se RabbitConsumer está selecionado e escolha OK.
No Gerenciador de Soluções, expanda o AppHost e clique duas vezes em Program.cs.
Localize o seguinte código:
builder.AddProject<WebApp>("webapp") .WithReference(catalogApi);
Imediatamente após esse código, para adicionar o projeto RabbitConsumer à orquestração do .NET Aspire, adicione o seguinte código:
builder.AddProject<Projects.RabbitConsumer>("consumers") .WithReference(messaging);
Configurar o projeto consumidor de mensagem
Para recebermos mensagens no novo projeto de consumidor de mensagens, devemos configurá-lo para usar o serviço de suporte do RabbitMQ do AppHost:
No Visual Studio, no Gerenciador de Soluções, clique com o botão direito do mouse no projeto RabbitConsumer, selecione Adicionar e, em seguida, selecione pacote .NET Aspire.
Na caixa de texto de pesquisa, no final do texto existente, digite RabbitMQ.
Selecione o pacote Aspire.RabbitMQ.Client.
Na lista Versão, selecione a versão 8.0.0 mais recente e selecione Instalar.
Se a caixa de diálogo Visualizar alterações aparecer, selecione Aplicar.
Na caixa de diálogo Aceitação da Licença, selecione Aceito.
No Gerenciador de Soluções, clique com o botão direito do mouse no projeto RabbitConsumer, aponte para Adicionar e selecione Referência do Projeto.
Na lista de projetos, verifique se eShop.ServiceDefaults está selecionado e escolha OK.
No Gerenciador de Soluções, expanda o projeto RabbitConsumer e clique duas vezes no Program.cs.
Remova todo o código padrão e substitua-o pelas seguintes linhas:
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; var builder = Host.CreateApplicationBuilder(args); builder.AddServiceDefaults(); builder.AddRabbitMQClient("messaging"); var host = builder.Build(); host.Run();
Observe que o código usa a orquestração do .NET Aspire para adicionar o serviço RabbitMQ ao projeto consumidor. Você usará esse serviço para recuperar mensagens.
Receber uma mensagem do RabbitMQ
Para receber uma mensagem, devemos criar um componente que seja executado em segundo plano aguardando a chegada das mensagens. Use uma classe BackgroundService
para esta tarefa:
No Gerenciador de Soluções, clique com o botão direito do mouse no projeto RabbitConsumer, aponte para Adicionar e selecione Classe.
Na caixa de texto Nome, digite CatalogProcessingJob e selecione Adicionar.
Na classe CatalogProcessingJob.cs, remova todo o código padrão e substitua-o pelas seguintes linhas:
namespace RabbitConsumer; using System.Text; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using RabbitMQ.Client; using RabbitMQ.Client.Events; public class CatalogProcessingJob : BackgroundService { private readonly ILogger<CatalogProcessingJob> _logger; private readonly IConfiguration _config; private readonly IServiceProvider _serviceProvider; private IConnection? _messageConnection; private IModel? _messageChannel; private EventingBasicConsumer consumer; public CatalogProcessingJob(ILogger<CatalogProcessingJob> logger, IConfiguration config, IServiceProvider serviceProvider, IConnection? messageConnection) { _logger = logger; _config = config; _serviceProvider = serviceProvider; } protected override Task ExecuteAsync(CancellationToken stoppingToken) { string queueName = "catalogEvents"; _messageConnection = _serviceProvider.GetRequiredService<IConnection>(); _messageChannel = _messageConnection.CreateModel(); _messageChannel.QueueDeclare(queue: queueName, durable: false, exclusive: false, autoDelete: false, arguments: null); consumer = new EventingBasicConsumer(_messageChannel); consumer.Received += ProcessMessageAsync; _messageChannel.BasicConsume(queue: queueName, autoAck: true, consumer: consumer); return Task.CompletedTask; } public override async Task StopAsync(CancellationToken cancellationToken) { await base.StopAsync(cancellationToken); consumer.Received -= ProcessMessageAsync; _messageChannel?.Dispose(); } private void ProcessMessageAsync(object? sender, BasicDeliverEventArgs args) { string messagetext = Encoding.UTF8.GetString(args.Body.ToArray()); _logger.LogInformation("All products retrieved from the catalog at {now}. Message Text: {text}", DateTime.Now, messagetext); var message = args.Body; } }
No Gerenciador de Soluções, no projeto RabbitConsumer, clique duas vezes no Program.cs.
Localize o seguinte código:
builder.AddRabbitMQClient("messaging");
Logo após essa linha, adicione o seguinte código:
builder.Services.AddHostedService<CatalogProcessingJob>();
Testar a solução
Vamos testar nosso serviço de suporte do RabbitMQ e os microsserviços que enviam e recebem mensagens:
No Visual Studio, para iniciar o aplicativo no modo de depuração, pressione F5 ou selecione Debug > Start Debugging.
Se a mensagem Iniciar Docker Desktop aparecer, selecione Sim. O aplicativo é iniciado e exibe o painel do .NET Aspire em uma guia do navegador.
No painel do .NET Aspire, na lista de Recursos, observe que a lista inclui um novo contêiner com o nome de sistema de mensagens. A origem inclui rabbitmq:3. Esse contêiner executa o agente de mensagens do RabbitMQ.
Na navegação à esquerda, selecione Console.
Na lista Selecionar um recurso, escolha sistema de mensagens. A página exibe os logs de console do agente do RabbitMQ. Observe que as últimas mensagens indicam que o RabbitMQ concluiu a inicialização e aceitou uma conexão. Essa conexão é do projeto RabbitConsumer receptor.
Na navegação à esquerda, selecione Recursos.
Na linha do projeto webapp, na coluna Pontos de Extremidade, selecione um dos links. A home page da Northern Traders se abre e exibe o catálogo de produtos. Esta página envia uma mensagem para a fila do RabbitMQ.
Volte para o painel do .NET Aspire. Na navegação à esquerda, selecione Console.
Na lista Selecionar um recurso, escolha sistema de mensagens. Observe que o RabbitQ aceitou uma segunda conexão. Essa conexão é do projeto Catalog.API.
Na lista Selecionar um recurso, selecione consumidores. Esse log é para o projeto RabbitConsumer. A entrada final exibe a mensagem "Obtendo todos os itens no catálogo". Esta mensagem foi recuperada do RabbitMQ e registrada em log.