Overview
RabbitMQ es un sistema de mensajería de código abierto que se utiliza para enviar y recibir mensajes, generalmente en un sistema distribuido. RabbitMQ es una implementación de AMQP (Advanced Message Queuing Protocol), que es un protocolo de mensajería estándar para la mensajería orientada a mensajes.
Este broker de mensajería es muy utilizado con el patrón Publih/Subscribe y arquitecturas orientadas a eventos para la comunicación entre sistemas distribuidos.
Propósito y alcance
El objetivo de la librería CodeDesignPlus.Net.RabbitMQ
es administrar y gestionar la conexión con RabbitMQ para la publicación y suscripción de eventos en aplicaciones .NET Core implementando la interfaz IMessage
de CodeDesignPlus.Net.PubSub
. Esta biblioteca proporciona un conjunto completo de herramientas y servicios para capturar, almacenar y reproducir eventos, facilitando la construcción de sistemas robustos y escalables basados en eventos.
Principales características
- Implementación de la interfaz
IMessage
deCodeDesignPlus.Net.PubSub
. - Colas de Mensajes: RabbitMQ permite la creación y gestión de colas donde los mensajes se almacenan hasta que los consumidores los procesen.
- Intercambio de mensajes: RabbitMQ permite la publicación de mensajes en un intercambio, que luego se enrutan a las colas.
- Consumidores: RabbitMQ permite la creación de consumidores que escuchan las colas y procesan los mensajes.
- Publicadores: RabbitMQ permite la publicación de mensajes en los intercambios.
- Dead Letter Exchange: RabbitMQ permite la configuración de un intercambio de mensajes muertos para enrutar mensajes que no se pudieron procesar.
- Retención de mensajes: RabbitMQ permite la configuración de la retención de mensajes en las colas.
- TTL (Time To Live): RabbitMQ permite la configuración de un tiempo de vida para los mensajes en las colas.
- Prefetch Count: RabbitMQ permite la configuración de la cantidad de mensajes que se pueden consumir de una cola.
- Auto Acknowledge: RabbitMQ permite la configuración de la confirmación automática de los mensajes consumidos.
Casos de uso típicos
- Comunicación Asíncrona: Ideal para sistemas distribuidos que necesitan comunicación asíncrona entre componentes.
- Colas de Mensajes: Permite la creación de colas para gestionar el flujo de mensajes y asegurar la entrega.
- Intercambios y Claves de Enrutamiento: Ofrece flexibilidad en la distribución y enrutamiento de mensajes mediante intercambios y claves de enrutamiento.
- Escalabilidad: Escalable y adecuado para manejar grandes volúmenes de mensajes.
- Protocolo AMQP: Implementa el protocolo AMQP, que es estándar para la comunicación de mensajes.
Componentes principales
ChannelProvider
: Proveedor de canales de RabbitMQ.RabbitConnection
: Conexión con RabbitMQ.RabbitPubSubService
: Servicio de publicación y suscripción de mensajes que implementa la interfazIMessage
deCodeDesignPlus.Net.PubSub
.QueueNameAttribute
: Atributo para definir el nombre de la cola de mensajes.
Directorysrc
DirectoryCodeDesignPlus.Net.RabbitMQ
DirectoryAttributes
- QueueNameAttribute.cs
DirectoryExceptions
- RabbitMQException.cs
DirectoryExtensions
- ServiceCollectionExtensions.cs
DirectoryServices
- ChannelProvider.cs
- InitializeBackgroundService.cs
- RabbitConnection.cs
- RabbitPubSubService.cs
DirectoryCodeDesignPlus.Net.RabbitMQ.Abstractions
- ChannelModel.cs
- IChannelProvider.cs
- IRabbitConnection.cs
- IRabbitPubSub.cs
DirectoryOptions
- QueueArguments.cs
- RabitMQOptions.cs
Primeros pasos
En esta sección, se describen los pasos necesarios para comenzar a trabajar con la librería CodeDesignPlus.Net.RabbitMQ
.
Requisitos previos
- .NET 8 o superior.
- Conocimientos básicos de patrones de diseño y sistemas distribuidos.
- Conocimientos sobre la arquitectura orientada a eventos (Event-Driven).
- Inyección de dependencias en aplicaciones .NET.
Instalación
Para instalar la biblioteca CodeDesignPlus.Net.RabbitMQ
, agrega el paquete NuGet a tu proyecto:
dotnet add package CodeDesignPlus.Net.RabbitMQ
Install-Package CodeDesignPlus.Net.RabbitMQ
<PackageReference Include="CodeDesignPlus.Net.RabbitMQ" Version="1.0.0" />
Configuración básica
-
Asignar las opciones de configuración en el
appsettings.json
:{"Core": {"Business": "CodeDesignPlus","AppName": "sample-rabbitmq-producer","Version": "v1","Description": "Sample of CodeDesignPlus.Net.Core","Contact": {"Name": "CodeDesignPlus","Email": "custom@outlook.com"}},"RabbitMQ": {"Enable": true,"Host": "localhost","Port": 5672,"UserName": "admin","Password": "password","RetryInterval": 1000,"MaxRetryAttempts": 5,"UseQueue": false}} -
Registra los servicios el contenedor de dependencias de tu aplicación:
// ...services.AddRabbitMQ<Program>(configuration);
Ejemplo rápido
El proyecto de ejemplo CodeDesignPlus.Net.RabbitMQ.Sample contiene dos ejemplos de cómo publicar y suscribirse a mensajes en RabbitMQ.
Es proyecto de ejemplo CodeDesignPlus.Net.RabbitMQ.Producer.Sample
contiene un ejemplo de cómo publicar mensajes en RabbitMQ.
using CodeDesignPlus.Net.RabbitMQ.Extensions;using CodeDesignPlus.Net.PubSub.Abstractions;using Microsoft.Extensions.Configuration;using Microsoft.Extensions.DependencyInjection;using CodeDesignPlus.Net.RabbitMQ.Producer.Sample;
var configuration = new ConfigurationBuilder() .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .Build();
var serviceCollection = new ServiceCollection();
serviceCollection.AddLogging();serviceCollection.AddRabbitMQ<Program>(configuration);
var serviceProvider = serviceCollection.BuildServiceProvider();
var pubSub = serviceProvider.GetRequiredService<IPubSub>();
do{ var userCreatedDomainEvent = new UserCreatedDomainEvent(Guid.NewGuid(), "John Doe", "john.doe@codedesignplus.com");
await pubSub.PublishAsync(userCreatedDomainEvent, CancellationToken.None);
Console.WriteLine("Message published successfully");
await Task.Delay(1000);} while ( true);
-
Configuración de RabbitMQ en
appsettings.json
:{"Core": {"Business": "CodeDesignPlus","AppName": "sample-rabbitmq-producer","Version": "v1","Description": "Sample of CodeDesignPlus.Net.Core","Contact": {"Name": "CodeDesignPlus","Email": "custom@outlook.com"}},"RabbitMQ": {"Enable": true,"Host": "localhost","Port": 5672,"UserName": "admin","Password": "password","RetryInterval": 1000,"MaxRetryAttempts": 5,"UseQueue": false}} -
Definir la entidad de usuario:
Hemos creado la entidad UserEntity, la cual estará vinculada al mensaje que se publicará en RabbitMQ. Esto proporcionará al consumidor el contexto necesario sobre la entidad que ha experimentado una modificación.
using System;using CodeDesignPlus.Net.Core.Abstractions;namespace CodeDesignPlus.Net.RabbitMQ.Producer.Sample;public class UserEntity : IEntity{public Guid Id { get; set; }public bool IsActive { get; set; }public Instant CreatedAt { get; set; }public Guid CreatedBy { get; set; }public Instant? UpdatedAt { get; set; }public Guid? UpdatedBy { get; set; }public required string Name { get; set; }public required string Email { get; set; }public string? Password { get; set; }} -
Creamos los eventos de dominio:
Hemos creado el evento de dominio UserCreatedDomainEvent, el cual se publicará en RabbitMQ cuando se cree un nuevo usuario.
using CodeDesignPlus.Net.Core.Abstractions;using CodeDesignPlus.Net.Core.Abstractions.Attributes;namespace CodeDesignPlus.Net.RabbitMQ.Producer.Sample;[EventKey<UserEntity>(1, "created")]public class UserCreatedDomainEvent(Guid aggregateId,string name,string email,string? password = null,Guid? eventId = null,Instant? occurredAt = null,Dictionary<string, object>? metadata = null) : DomainEvent(aggregateId, eventId, occurredAt, metadata){public string Name { get; } = name;public string Email { get; } = email;public string? Password { get; set; } = password;public static UserCreatedDomainEvent Create(Guid aggregateId, string name, string email, string? password = null){return new UserCreatedDomainEvent(aggregateId, name, email, password);}} -
Registraremos los servicios necesarios en el contenedor de dependencias.
serviceCollection.AddRabbitMQ<Program>(configuration); -
Obtenemos la instancia de
IPubSub
:var producer = serviceProvider.GetRequiredService<IPubSub>(); -
Creamos y publicamos el evento
UserCreatedDomainEvent
:var userCreatedDomainEvent = new UserCreatedDomainEvent(Guid.NewGuid(), "John Doe", "john.doe@codedesignplus.com");await producer.PublishAsync(userCreatedDomainEvent, CancellationToken.None);
El proyecto de ejemplo CodeDesignPlus.Net.RabbitMQ.Consumer.Sample
contiene un ejemplo de cómo suscribirse a mensajes en RabbitMQ.
using CodeDesignPlus.Net.RabbitMQ.Extensions;
var builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddConsole();
builder.Services.AddRabbitMQ<Program>(builder.Configuration);
var host = builder.Build();host.Run();
-
Configuración de RabbitMQ en
appsettings.json
:{"Core": {"Business": "CodeDesignPlus","AppName": "sample-rabbitmq-consumer","Version": "v1","Description": "Sample of CodeDesignPlus.Net.Core","Contact": {"Name": "CodeDesignPlus","Email": "custom@outlook.com"}},"RabbitMQ": {"Enable": true,"Host": "localhost","Port": 5672,"UserName": "admin","Password": "password","RetryInterval": 1000,"MaxRetryAttempts": 5}} -
Definir la entidad de usuario:
Hemos creado la entidad UserEntity, que almacenará la información del evento y contendrá solo los datos necesarios para proporcionar el contexto requerido por el consumidor (proyección).
using System;using CodeDesignPlus.Net.Core.Abstractions;namespace CodeDesignPlus.Net.RabbitMQ.Consumer.Sample;public class UserEntity : IEntity{public Guid Id { get; set; }public bool IsActive { get; set; }public Instant CreatedAt { get; set; }public Guid CreatedBy { get; set; }public Instant? UpdatedAt { get; set; }public Guid? UpdatedBy { get; set; }public required string Name { get; set; }public required string Email { get; set; }public string? Password { get; set; }} -
Creamos los eventos de dominio:
Hemos creado el evento de dominio UserCreatedDomainEvent, que representa la estructura del evento de dominio a ser consumido.
using CodeDesignPlus.Net.Core.Abstractions;using CodeDesignPlus.Net.Core.Abstractions.Attributes;namespace CodeDesignPlus.Net.RabbitMQ.Consumer.Sample;[EventKey<UserEntity>(1, "created", "sample-rabbitmq-producer")]public class UserCreatedEvent(Guid aggregateId,string name,string email,string? password = null,Guid? eventId = null,Instant? occurredAt = null,Dictionary<string, object>? metadata = null) : DomainEvent(aggregateId, eventId, occurredAt, metadata){public string Name { get; } = name;public string Email { get; } = email;public string? Password { get; set; } = password;public static UserCreatedEvent Create(Guid aggregateId, string name, string email, string? password = null){return new UserCreatedEvent(aggregateId, name, email, password);}} -
Creamos el event handler:
Hemos creado el event handler
UserCreatedDomainEventHandler
, el cual se encargará de procesar el evento de dominioUserCreatedDomainEvent
cuando se publique en RabbitMQ.El event handler es registrado en el contenedor de dependencias automaticamente por la librería
CodeDesignPlus.Net.PubSub
.using CodeDesignPlus.Net.PubSub.Abstractions;using CodeDesignPlus.Net.RabbitMQ.Attributes;using CodeDesignPlus.Net.Serializers;namespace CodeDesignPlus.Net.RabbitMQ.Consumer.Sample;[QueueName("userentity", "register-user")]public class UserCreatedEventHandler(ILogger<UserCreatedEventHandler> logger) : IEventHandler<UserCreatedEvent>{public Task HandleAsync(UserCreatedEvent data, CancellationToken token){logger.LogInformation("Invoked Event: {Json}", JsonSerializer.Serialize(data));return Task.CompletedTask;}} -
Registraremos los servicios necesarios en el contenedor de dependencias.
builder.Services.AddRabbitMQ<Program>(builder.Configuration);
Métodos de extensión
La librería CodeDesignPlus.Net.RabbitMQ
proporciona una serie de métodos de extensión para facilitar la configuración y el uso de RabbitMQ en aplicaciones .NET Core.
ServiceCollectionExtensions
ServiceCollectionExtensions
contiene los métodos de extensión para registrar los servicios necesarios en el contenedor de dependencias.
Opciones de configuración
La librería CodeDesignPlus.Net.RabbitMQ
proporciona una serie de opciones de configuración para personalizar la configuración de RabbitMQ en aplicaciones .NET Core.
Servicios
La librería CodeDesignPlus.Net.RabbitMQ
proporciona una serie de servicios para administrar y gestionar la conexión con RabbitMQ en aplicaciones .NET Core.
ChannelProvider
ChannelProvider
es un servicio que proporciona canales de RabbitMQ para la publicación y suscripción de mensajes.
RabbitConnection
RabbitConnection
es un servicio que implementa la interfaz IRabbitConnection
para la conexión con RabbitMQ.
RabbitPubSubService
RabbitPubSubService
es un servicio que implementa la interfaz IMessage
de CodeDesignPlus.Net.PubSub
para la publicación y suscripción de mensajes en RabbitMQ.
Conclusiones
La librería CodeDesignPlus.Net.RabbitMQ
proporciona una solución completa para la publicación y suscripción de mensajes en RabbitMQ en aplicaciones .NET Core. Con esta biblioteca, puedes implementar fácilmente la comunicación asíncrona entre componentes y construir sistemas distribuidos robustos y escalables basados en eventos.