Ejercicio: Envío de mensajes entre microservicios a través de RabbitMQ

Completado

RabbitMQ es un agente de mensajes confiable que proporciona intercambios de mensajería flexibles y colas. Para enviar y recibir mensajes a través de RabbitMQ en un proyecto de .NET Aspire, debe agregar un contenedor rabbitMQ y, a continuación, crear código que envíe mensajes de un microservicio y lo reciba en otro.

En este ejercicio, enviará mensajes a una cola desde el proyecto Catalog.API. Agregará un nuevo proyecto de servicio en segundo plano que recibe esos mensajes de la cola y los enviará al registro de consola para su visualización.

Requisitos previos de instalación

Los requisitos previos para .NET Aspire son:

  • .NET 8
  • Versión preliminar de Visual Studio 2022
  • Docker Desktop o Podman
  • Carga de trabajo de .NET Aspire en Visual Studio

Si ya tiene estos paquetes instalados, puede saltárselos para empezar a trabajar con RabbitMQ.

Instalación de .NET 8

Siga este vínculo de .NET 8 y seleccione el instalador correcto para el sistema operativo. Por ejemplo, si usa Windows 11 y un procesador moderno, seleccione el SDK de .NET 8 para Windows x64.

Una vez completada la descarga, ejecute el instalador y siga las instrucciones. En una ventana de terminal, ejecute el siguiente comando para comprobar que la instalación se realizó correctamente:

dotnet --version

Debería ver el número de versión del SDK de .NET que instaló. Por ejemplo:

8.0.300-preview.24203.14

Instalación de Visual Studio 2022 Preview

Siga este vínculo de Visual Studio 2022 Preview y seleccione Descargar versión preliminar. Una vez completada la descarga, ejecute el instalador y siga las instrucciones.

Instalar Docker Desktop

Siga este vínculo de Docker Desktop y seleccione el instalador correcto para el sistema operativo. Una vez completada la descarga, ejecute el instalador y siga las instrucciones. Para obtener el mejor rendimiento y compatibilidad, use el back-end WSL 2.

Abra la aplicación Docker Desktop y acepte el contrato de servicio.

Instalación de la carga de trabajo de .NET Aspire en Visual Studio

Instale la carga de trabajo de .NET Aspire mediante la CLI de NET:

  1. Abra un terminal.

  2. Actualice las cargas de trabajo de .NET con este comando:

    dotnet workload update
    

    Debería ver un mensaje que indica que las cargas de trabajo se actualizaron correctamente.

    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 la carga de trabajo de .NET Aspire con este comando:

    dotnet workload install aspire
    

    Debería ver un mensaje que indica que la carga de trabajo de 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. Compruebe que la carga de trabajo de .NET Aspire está instalada con este comando:

    dotnet workload list
    

    Debería ver los detalles de la carga de trabajo de .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 proyecto

Vamos a usar git para obtener una aplicación de ejemplo, que aún no usa un agente de mensajes:

  1. En la línea de comandos, vaya a una carpeta de su elección, donde pueda trabajar con código.

  2. Ejecute el siguiente comando para clonar la aplicación de ejemplo de eShop:

    git clone -b aspire-rabbitmq  https://github.com/MicrosoftDocs/mslearn-aspire-starter
    

Creación del contenedor RabbitMQ

Comencemos agregando RabbitMQ al proyecto host de la aplicación. Cuando se inicia la solución, .NET Aspire agrega un contenedor RabbitMQ a la aplicación y pasa referencias a los proyectos que lo usan:

  1. Abra Visual Studio y seleccione Abrir un proyecto o solución.

  2. Vaya a la carpeta donde ha clonado el proyecto.

  3. Haga doble clic en la carpeta de inicio, seleccione la solución eShop.rabbitmq.sln y, a continuación, seleccione Abrir.

  4. En Explorador de soluciones, haga clic con el botón derecho en el proyectoeShop.AppHost, seleccione Agregar y, a continuación, seleccione paquete de .NET Aspire.

  5. En el cuadro de texto de búsqueda, al final del texto existente, escriba RabbitMQ.

  6. Seleccione Paquete Aspire.Hosting.RabbitMQ.

  7. En la lista Versión, seleccione la versión más reciente 8.0.0 y, a continuación, seleccione Instalar.

  8. Si aparece el cuadro de diálogo Vista previa de cambios, seleccione Aplicar.

  9. En el diálogo Aceptación de licencia, seleccione Acepto.

  10. En Explorador de soluciones, expanda el proyecto eShop.AppHost y, a continuación, haga doble clic en Program.cs.

  11. Busque la línea de código siguiente:

    var builder = DistributedApplication.CreateBuilder(args);
    
  12. Inmediatamente después de ese código, para registrar un servidor RabbitMQ, agregue este código:

    var messaging = builder.AddRabbitMQ("messaging");
    
  13. Busque el código siguiente, que registra el proyecto Catalog.API para la orquestación de .NET Aspire:

    var catalogApi = builder.AddProject<Catalog_API>("catalog-api")
        .WithReference(catalogDb);
    
  14. Para pasar el servicio RabbitMQ al proyecto Catalog.API, modifique ese código para que coincida con este código:

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

Adición de RabbitMQ al proyecto Catalog.API

Ahora, podemos instalar y configurar RabbitMQ en el proyecto Catalog.API:

  1. En Visual Studio, en Explorador de soluciones, haga clic con el botón derecho en el proyectoCatalog.API, seleccione Agregar y, a continuación, seleccione paquete de .NET Aspire.

  2. En el cuadro de texto de búsqueda, al final del texto existente, escriba RabbitMQ.

  3. Seleccione el paquete Aspire.RabbitMQ.Client.

  4. En la lista Versión, seleccione la versión más reciente 8.0.0 y, a continuación, seleccione Instalar.

  5. Si aparece el cuadro de diálogo Vista previa de cambios, seleccione Aplicar.

  6. En el diálogo Aceptación de licencia, seleccione Acepto.

  7. En Explorador de soluciones, expanda el proyecto Catalog.API y, a continuación, haga doble clic en Program.cs.

  8. En el archivo Program.cs, busque la siguiente línea de código:

    var builder = WebApplication.CreateBuilder(args);
    
  9. Inmediatamente después de esa línea, para registrar la conexión RabbitMQ, agregue este código:

    builder.AddRabbitMQClient("messaging");
    

Enviar un mensaje a una cola de RabbitMQ

Cuando un usuario solicita los elementos del catálogo, queremos enviar un mensaje a una cola rabbitMQ que describa los detalles de la solicitud. Vamos a agregar el código:

  1. En Explorador de soluciones expanda Catalog.API > API y haga doble clic en CatalogApi.cs.

  2. Busque el siguiente código, que declara el método GetAllItems():

    public static async Task<Results<Ok<PaginatedItems<CatalogItem>>, BadRequest<string>>> GetAllItems(
        [AsParameters] PaginationRequest paginationRequest,
        [AsParameters] CatalogServices services)
    {
    
  3. Para usar la inserción de dependencias para obtener la conexión a RabbitMQ, modifique el código para que coincida con las líneas siguientes:

    public static async Task<Results<Ok<PaginatedItems<CatalogItem>>, BadRequest<string>>> GetAllItems(
        [AsParameters] PaginationRequest paginationRequest,
        [AsParameters] CatalogServices services,
        RabbitMQ.Client.IConnection connection)
    {
    
  4. Busque la línea de código siguiente:

    var totalItems = await services.DbContext.CatalogItems
        .LongCountAsync();
    
  5. Inmediatamente después de esa línea, para crear un canal de mensajería rabbitMQ, agregue este código:

    var channel = connection.CreateModel();
    
  6. En la línea siguiente, para crear una cola de mensajes, agregue este código:

    channel.QueueDeclare(queue: "catalogEvents",
                         durable: false,
                         exclusive: false,
                         autoDelete: false,
                         arguments: null);
    
  7. En la línea siguiente, para enviar el mensaje, agregue 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);
    

Adición de un proyecto de consumidor de mensajes

Para recibir mensajes de la cola rabbitMQ, vamos a crear un nuevo proyecto:

  1. En el Explorador de soluciones, haga clic con el botón secundario en Solución, haga clic en Agregar y seleccione Nuevo proyecto.

  2. En el cuadro de texto Buscar plantillas, escriba Consola.

  3. Seleccione la plantilla Aplicación de consola de C# y, a continuación, seleccione Siguiente.

  4. En el cuadro de texto Nombre del proyecto, escriba RabbitConsumer y, a continuación, seleccione Siguiente.

  5. En la lista Framework, asegúrese de que está seleccionado .NET 8.0 y, a continuación, seleccione Crear.

  6. En el Explorador de soluciones, haga clic con el botón derecho en el proyecto AppHost, seleccione Agregary, a continuación, seleccione Referencia del proyecto.

  7. En la lista de proyectos, asegúrese de que RabbitConsumer está seleccionado y, a continuación, seleccione Aceptar.

    Captura de pantalla que muestra cómo agregar una referencia al proyecto AppHost que hace referencia al proyecto RabbitConsumer.

  8. En Explorador de soluciones, expanda el proyecto AppHost y, a continuación, haga doble clic en Program.cs.

  9. Busque el siguiente código:

    builder.AddProject<WebApp>("webapp")
        .WithReference(catalogApi);
    
  10. Inmediatamente después de ese código, para agregar el proyecto RabbitConsumer a la orquestación aspire de .NET, agregue el código siguiente:

    builder.AddProject<Projects.RabbitConsumer>("consumers")
        .WithReference(messaging);
    

Configuración del proyecto de consumidor de mensajes

Para poder recibir mensajes en el nuevo proyecto de consumidor de mensajes, debemos configurarlos para usar el servicio de respaldo RabbitMQ desde AppHost:

  1. En Visual Studio, en Explorador de soluciones, haga clic con el botón derecho en el proyectoRabbitConsumer, seleccione Agregar y, a continuación, seleccione paquete de .NET Aspire.

  2. En el cuadro de texto de búsqueda, al final del texto existente, escriba RabbitMQ.

  3. Seleccione el paquete Aspire.RabbitMQ.Client.

  4. En la lista Versión, seleccione la versión más reciente 8.0.0 y, a continuación, seleccione Instalar.

  5. Si aparece el cuadro de diálogo Vista previa de cambios, seleccione Aplicar.

  6. En el diálogo Aceptación de licencia, seleccione Acepto.

  7. En el Explorador de soluciones, haga clic con el botón derecho en el proyecto RabbitConsumer, seleccione Agregary, a continuación, seleccione Referencia del proyecto.

  8. En la lista de proyectos, asegúrese de que eShop.ServiceDefaults está seleccionado y, a continuación, seleccione Aceptar.

    Captura de pantalla que muestra cómo agregar una referencia al proyecto RabbitConsumer que hace referencia al proyecto ServiceDefaults.

  9. En Explorador de soluciones, expanda el proyecto RabbitConsumer y, a continuación, haga doble clic en Program.cs.

  10. Quite todo el código predeterminado y reemplácelo por las siguientes líneas:

    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 el código usa la orquestación Aspire de .NET para agregar el servicio RabbitMQ al proyecto de consumidor. Usará ese servicio para recuperar mensajes.

Recepción de un mensaje rabbitMQ

Para recibir un mensaje, debemos crear un componente que se ejecute en segundo plano esperando a que lleguen los mensajes. Use una BackgroundService clase para esta tarea:

  1. En el Explorador de soluciones, haga clic con el botón derecho en el proyecto RabbitConsumer, seleccione Agregar y, a continuación, seleccione Clase.

  2. En el cuadro de texto Nombre, escriba CatalogProcessingJob y, a continuación, seleccione Agregar.

  3. En la clase CatalogProcessingJob.cs, quite todo el código predeterminado y reemplácelo por las líneas siguientes:

     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. En el Explorador de soluciones, en el proyecto RabbitConsumer, haga doble clic en Program.cs.

  5. Busque el siguiente código:

    builder.AddRabbitMQClient("messaging");
    
  6. Inmediatamente después de esa línea, añada el siguiente código:

    builder.Services.AddHostedService<CatalogProcessingJob>();
    

Probar la solución

Vamos a probar nuestro servicio de respaldo RabbitMQ y los microservicios que envían y reciben mensajes:

  1. En Visual Studio, para iniciar la aplicación en modo de depuración, presione F5 o seleccione Depurar > Iniciar depuración.

  2. Si aparece el mensaje Iniciar Docker Desktop, seleccione . La aplicación se inicia y muestra el panel de .NET Aspire en una pestaña del explorador.

  3. En el panel de .NET Aspire, en la lista de Recursos, observe que la lista incluye un nuevo contenedor con la mensajería de nombres. El origen incluye rabbitmq:3. Este contenedor ejecuta el agente de mensajes rabbitMQ.

    Captura de pantalla que muestra un contenedor RabbitMQ mostrado en el panel de .NET Aspire.

  4. En el panel de navegación de la izquierda, seleccione Consola.

  5. En la lista Seleccionar un recurso, seleccione mensajería. En la página se muestran los registros de consola del agente RabbitMQ. Observe que los últimos mensajes indican que RabbitMQ completó su inicio y aceptó una conexión. Esta conexión procede del proyecto RabbitConsumer receptor.

  6. En el panel de navegación de la izquierda, seleccione Recursos.

  7. En la línea del proyecto de aplicación web, en la columna Puntos de conexión, seleccione uno de los vínculos. Se abre la página principal de Northern Traders y se muestra el catálogo de productos. Esta página envía un mensaje a la cola RabbitMQ.

    Captura de pantalla que muestra cómo acceder al punto de conexión del proyecto de WebApp desde el panel de .NET Aspire.

  8. Vuelva al panel de .NET Aspire. En el panel de navegación de la izquierda, seleccione Consola.

  9. En la lista Seleccionar un recurso, seleccione mensajería. Observe que RabbitQ ha aceptado una segunda conexión. Esta conexión procede del proyecto Catalog.API.

  10. En la lista Seleccionar un recurso, seleccione consumidores. Este registro es para el proyecto RabbitConsumer. La entrada final muestra el mensaje "Obtener todos los elementos del catálogo". Este mensaje se ha recuperado de RabbitMQ y se ha registrado.

    Captura de pantalla que muestra el mensaje recuperado de la cola RabbitMQ y mostrado en los registros de consola del proyecto de consumidor.