Envío de mensajes con RabbitMQ

Completado

Es fácil escribir código que crea colas, envía mensajes y recibe mensajes de RabbitMQ. En una solución de .NET Aspire, también tiene ayuda para crear el contenedor RabbitMQ y realizar conexiones a él desde microservicios.

En su distribuidor de equipos al aire libre, ha decidido implementar RabbitMQ como agente de mensajes centralizado para el sitio web del catálogo de productos orientado al cliente. Quiere usar el componente RabbitMQ de .NET Aspire para administrar este agente y sus colas.

En esta unidad, aprenderá a crear un contenedor RabbitMQ y usarlo para enviar y recibir mensajes.

Uso del componente RabbitMQ de .NET Aspire

Cuando se usa RabbitMQ desde .NET, normalmente es necesario crear un objeto ConnectionFactory con una cadena de conexión y, a continuación, usarlo para realizar conexiones con el servicio. En un proyecto de .NET Aspire, es más fácil administrar la conexión RabbitMQ porque:

  • Registra una conexión y una cadena de conexión en el proyecto AppHost.
  • Al pasar una referencia al servicio para consumir proyectos, pueden usar la inserción de dependencias para obtener una conexión a RabbitMQ. No es necesario crear y configurar sus propias conexiones.

Configuración de RabbitMQ en el host de la aplicación

En .NET Aspire, debe instalar el componente de hospedaje RabbitMQ en el host de la aplicación:

dotnet add package Aspire.Hosting.RabbitMQ

Ahora, puede registrar el servicio RabbitMQ y pasarlo a proyectos que lo usen:

// Service registration
var rabbit = builder.AddRabbitMQ("messaging");

// Service consumption
builder.AddProject<Projects.CatalogAPI>()
       .WithReference(rabbit);

El AppHost administra la conexión de todos los proyectos de la solución.

Configuración de Rab

A continuación, agregue el componente RabbitMQ de .NET Aspire a cada proyecto que lo use:

dotnet add package Aspire.RabbitMQ.Client

Para obtener una referencia al agente de mensajes RabbitMQ, llame al método AddRabbitMQClient():

builder.AddRabbitMQClient("messaging");

Ahora, puede usar la inserción de dependencias para obtener la conexión a RabbitMQ:

public class CatalogAPI(IConnection rabbitConnection)
{
    // Send and receive messages here
}

Con la conexión, el siguiente paso es crear un canal de mensajería, de la siguiente manera:

var channel = connection.CreateModel();

Enviar mensajes

Una vez que tenga el canal de mensajería, puede usarlo para configurar colas, intercambios y otros componentes de la topología de mensajería. Por ejemplo, para crear una cola, use este código:

channel.QueueDeclare(queue: "catalogEvents",
    durable: false,
    exclusive: false,
    autoDelete: false,
    arguments: null);

Usa el método BasicPublish para enviar un mensaje a esta cola, pero el mensaje espera que el cuerpo sea una matriz de bytes:

var body = Encoding.UTF8.GetBytes("Getting all items in the catalog.");

channel.BasicPublish(exchange: string.Empty,
    routingKey: "catalogEvents",
    basicProperties: null,
    body: body);

Recepción de mensajes

En el componente receptor, se crea el canal de mensajería y la cola de la misma manera que para el remitente. Asegúrese de que el nombre de la cola coincide con el que creó en el componente de envío. De lo contrario, creará dos colas independientes y los mensajes no llegarán al destino correcto.

Debe crear un nuevo método EventingBasicConsumer() y registrar un método para controlar el evento Received:

var consumer = new EventingBasicConsumer(channel);
consumer.Received += ProcessMessageAsync;

El controlador de mensajes usa un objeto BasicDeliverEventArgs para obtener las propiedades del mensaje, incluido el cuerpo del mensaje. Debe recordar deserializar el cuerpo del mensaje:

private void ProcessMessageAsync(object? sender, BasicDeliverEventArgs args)
{
    string messagetext = Encoding.UTF8.GetString(args.Body.ToArray());
    logger.LogInformation("The message is: {text}", messagetext);
}

Por último, para comprobar la cola de nuevos mensajes, llame al método BasicConsume();

channel.BasicConsume(queue:  queueName,
                    autoAck: true, 
                    consumer: consumer);

Saber más