Exercício - Envie mensagens entre microsserviços através do RabbitMQ

Concluído

RabbitMQ é um agente de mensagens confiável que fornece trocas de mensagens flexíveis e filas. Para enviar e receber mensagens através do RabbitMQ em um projeto .NET Aspire , você deve adicionar um contêiner RabbitMQ e, em seguida, criar 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.

Pré-requisitos da instalação

Os pré-requisitos para o .NET Aspire são:

  • .NET 8
  • Pré-visualização do Visual Studio 2022
  • Docker Desktop ou Podman
  • Carga de trabalho do .NET Aspire no Visual Studio

Se você já tiver esses pacotes instalados, você pode pular para começar a trabalhar com o RabbitMQ.

Instalar o .NET 8

Siga este link do .NET 8 e selecione o instalador correto para seu sistema operacional. Por exemplo, se você estiver usando o Windows 11 e um processador moderno, selecione o x64 .NET 8 SDK para Windows.

Após a conclusão do download, execute o instalador e siga as instruções. Em uma janela do terminal, execute o seguinte comando para verificar se a instalação foi bem-sucedida:

dotnet --version

Você deve ver o número da versão do SDK do .NET que você instalou. Por exemplo:

8.0.300-preview.24203.14

Instalar o Visual Studio 2022 Preview

Siga este link do Visual Studio 2022 Preview e selecione Baixar visualização. Após a conclusão do download, execute o instalador e siga as instruções.

Instalar o Docker Desktop

Siga este link do Docker Desktop e selecione o instalador correto para seu sistema operacional. Após a conclusão do download, execute o instalador e siga as instruções. Para obter o melhor desempenho e compatibilidade, use o back-end WSL 2.

Abra o aplicativo Docker Desktop e aceite o contrato de serviço.

Instalar a carga de trabalho do .NET Aspire no Visual Studio

Instale a carga de trabalho do .NET Aspire usando a CLI do .NET:

  1. Abra um terminal.

  2. Atualize as cargas de trabalho do .NET com este comando:

    dotnet workload update
    

    Você verá uma mensagem informando que as cargas de trabalho foram atualizadas com êxito.

    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): .
    
  3. Instale a carga de trabalho do .NET Aspire com este comando:

    dotnet workload install aspire
    

    Você verá uma mensagem informando que a carga de trabalho do Aspire está 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.
    
  4. Verifique se a carga de trabalho do .NET Aspire está instalada com este comando:

    dotnet workload list
    

    Você deve 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.
    

Projeto Clone

Vamos usar git para obter um aplicativo de exemplo, que ainda não usa um agente de mensagens:

  1. Na linha de comando, navegue até uma pasta de sua escolha onde você pode trabalhar com código.

  2. 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 RabbitMQ

Vamos começar adicionando RabbitMQ ao projeto de host do aplicativo. Quando iniciamos a solução, o .NET Aspire adiciona um contêiner RabbitMQ ao aplicativo e passa referências para os projetos que o usam:

  1. Inicie o Visual Studio e selecione Abrir um projeto ou solução.

  2. Navegue até a pasta onde você clonou o projeto.

  3. Clique duas vezes na pasta Iniciar , selecione a solução eShop.rabbitmq.sln e, em seguida, selecione Abrir.

  4. 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 .

  5. Na caixa de texto de pesquisa, no final do texto existente, digite RabbitMQ.

  6. Selecione o pacote Aspire.Hosting.RabbitMQ .

  7. Na lista Versão, selecione a versão 8.0.0 mais recente e, em seguida, selecione Instalar.

  8. Se a caixa de diálogo Visualizar alterações for exibida, selecione Aplicar.

  9. Na caixa de diálogo Aceitação de licença , selecione Aceito.

  10. No Gerenciador de Soluções, expanda eShop.AppHost e clique duas vezes em Program.cs.

  11. Localize a seguinte linha de código:

    var builder = DistributedApplication.CreateBuilder(args);
    
  12. Imediatamente após esse código, para registrar um servidor RabbitMQ, adicione este código:

    var messaging = builder.AddRabbitMQ("messaging");
    
  13. 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);
    
  14. Para passar o serviço RabbitMQ para o projeto Catalog.API , altere esse código para corresponder a este código:

    var catalogApi = builder.AddProject<Catalog_API>("catalog-api")
        .WithReference(catalogDb)
        .WithReference(messaging);
    

Adicionar RabbitMQ ao projeto Catalog.API

Agora, podemos instalar e configurar o RabbitMQ no projeto Catalog.API:

  1. 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 Pacote .NET Aspire .

  2. Na caixa de texto de pesquisa, no final do texto existente, digite RabbitMQ.

  3. Selecione o pacote Aspire.RabbitMQ.Client .

  4. Na lista Versão, selecione a versão 8.0.0 mais recente e, em seguida, selecione Instalar.

  5. Se a caixa de diálogo Visualizar alterações for exibida, selecione Aplicar.

  6. Na caixa de diálogo Aceitação de licença , selecione Aceito.

  7. No Gerenciador de Soluções, expanda o projeto Catalog.API e clique duas vezes em Program.cs.

  8. No arquivo Program.cs, localize a seguinte linha de código:

    var builder = WebApplication.CreateBuilder(args);
    
  9. Imediatamente após essa linha, para registrar a conexão 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 descreva os detalhes da solicitação. Vamos adicionar esse código agora:

  1. No Gerenciador de Soluções, expanda Apis Catalog.API > e clique duas vezes em CatalogApi.cs.

  2. 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)
    {
    
  3. Para usar a injeção de dependência para obter a conexão com 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)
    {
    
  4. Localize a seguinte linha de código:

    var totalItems = await services.DbContext.CatalogItems
        .LongCountAsync();
    
  5. Imediatamente após essa linha, para criar um canal de mensagens RabbitMQ, adicione este código:

    var channel = connection.CreateModel();
    
  6. 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);
    
  7. 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 de consumidor de mensagem

Para receber mensagens da fila RabbitMQ, vamos criar um novo projeto:

  1. No Gerenciador de Soluções, clique com o botão direito do mouse na solução, aponte para Adicionar e selecione Novo Projeto.

  2. Na caixa de texto Pesquisar modelos , digite Console.

  3. Selecione o modelo Aplicativo de Console em C# e, em seguida, selecione Avançar.

  4. Na caixa de texto Nome do projeto, digite RabbitConsumer e selecione Avançar.

  5. Na lista Framework, verifique se .NET 8.0 está selecionado e selecione Criar.

  6. 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.

  7. Na lista de projetos, certifique-se de que RabbitConsumer está selecionado e, em seguida, selecione OK.

    Captura de tela mostrando como adicionar uma referência ao projeto AppHost que faz referência ao projeto RabbitConsumer.

  8. No Gerenciador de Soluções, expanda AppHost e clique duas vezes em Program.cs.

  9. Localize o seguinte código:

    builder.AddProject<WebApp>("webapp")
        .WithReference(catalogApi);
    
  10. 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 de consumidor de mensagem

Antes de podermos receber mensagens no novo projeto de consumidor de mensagens, devemos configurá-lo para usar o serviço de suporte RabbitMQ do AppHost:

  1. 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 .

  2. Na caixa de texto de pesquisa, no final do texto existente, digite RabbitMQ.

  3. Selecione o pacote Aspire.RabbitMQ.Client .

  4. Na lista Versão, selecione a versão 8.0.0 mais recente e, em seguida, selecione Instalar.

  5. Se a caixa de diálogo Visualizar alterações for exibida, selecione Aplicar.

  6. Na caixa de diálogo Aceitação de licença , selecione Aceito.

  7. 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.

  8. Na lista de projetos, verifique se eShop.ServiceDefaults está selecionado e selecione OK.

    Captura de tela mostrando como adicionar uma referência ao projeto RabbitConsumer que faz referência ao projeto ServiceDefaults.

  9. No Gerenciador de Soluções, expanda o projeto RabbitConsumer e clique duas vezes em Program.cs.

  10. 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 do consumidor. Você usará esse serviço para recuperar mensagens.

Receba uma mensagem RabbitMQ

Para receber uma mensagem, devemos criar uma integração que é executada em segundo plano esperando que as mensagens cheguem. Use uma BackgroundService classe para esta tarefa:

  1. No Gerenciador de Soluções, clique com o botão direito do mouse no projeto RabbitConsumer , aponte para Adicionar e selecione Classe.

  2. Na caixa de texto Nome , digite CatalogProcessingJob e selecione Adicionar.

  3. 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;
        }
    }
    
  4. No Gerenciador de Soluções, no projeto RabbitConsumer, clique duas vezes em Program.cs.

  5. Localize o seguinte código:

    builder.AddRabbitMQClient("messaging");
    
  6. Imediatamente após essa linha, adicione o seguinte código:

    builder.Services.AddHostedService<CatalogProcessingJob>();
    

Testar a solução

Vamos testar nosso serviço de suporte RabbitMQ e os microsserviços que enviam e recebem mensagens:

  1. No Visual Studio, para iniciar o aplicativo no modo de depuração, pressione F5 ou selecione Depurar > Iniciar Depuração.

  2. Se a mensagem Iniciar área de trabalho do Docker for exibida, selecione Sim. O aplicativo é iniciado e exibe o painel do .NET Aspire em uma guia do navegador.

  3. No painel do .NET Aspire , na lista de Recursos, observe que a lista inclui um novo contêiner com o nome das mensagens. A fonte inclui rabbitmq:3. Este contêiner executa o agente de mensagens RabbitMQ.

    Captura de tela mostrando um contêiner RabbitMQ exibido no painel do .NET Aspire .

  4. Na navegação à esquerda, selecione Console.

  5. Na lista Selecione um recurso, selecione mensagens. A página exibe os logs do console para o broker RabbitMQ. Observe que as últimas mensagens indicam que o RabbitMQ concluiu sua inicialização e aceitou uma conexão. Esta ligação é do projeto RabbitConsumer que o recebe.

  6. Na navegação à esquerda, selecione Recursos.

  7. Na linha do projeto webapp , na coluna Pontos de extremidade , selecione um dos links. A página inicial da Northern Traders é aberta e exibe o catálogo de produtos. Esta página envia uma mensagem para a fila RabbitMQ.

    Captura de tela mostrando como acessar o ponto de extremidade do projeto WebApp a partir do painel do .NET Aspire .

  8. Volte para o painel do .NET Aspire . Na navegação à esquerda, selecione Console.

  9. Na lista Selecione um recurso, selecione mensagens. Observe que o RabbitQ aceitou uma segunda conexão. Essa conexão é do projeto Catalog.API .

  10. Na lista Selecione um recurso, selecione consumidores. Este 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.

    Captura de tela mostrando a mensagem recuperada da fila do RabbitMQ e exibida nos logs do console para o projeto do consumidor.