Brighter and RabbitMQ: How to setup and use Brighter with RabbitMQ

Introduction to RabbitMQ RabbitMQ is one of the most widely used message brokers, implementing the Advanced Message Queuing Protocol (AMQP) to ensure reliable message delivery. Built on the Erlang programming language, it offers high scalability and fault tolerance, making it ideal for distributed systems. RabbitMQ acts as an intermediary that accepts messages from producers and delivers them to consumers, decoupling services in a microservices architecture. Requirement .NET 8 or superior A .NET project with these NuGet packages Paramore.Brighter.MessagingGateway.RMQ: Enables RabbitMQ integration. Paramore.Brighter.ServiceActivator.Extensions.DependencyInjection: Enable register Brighter with Microsoft DI. Paramore.Brighter.ServiceActivator.Extensions.Hosting: Hosts Brighter as a background service. Serilog.AspNetCore: For structured logging (optional but recommended). Brighter Recap Before continuing about AWS SNS/SQS configuration, let's recap what we already know about Brighter. Request (Command/Event) Define messages using IRequest: public class Greeting() : Event(Guid.NewGuid()) { public string Name { get; set; } = string.Empty; } Commands: Single-recipient operations (e.g., SendEmail). Events: Broadcast notifications (e.g., OrderShipped). Message Mapper Translates between Brighter messages and your app objects: public class GreetingMapper : IAmAMessageMapper { public Message MapToMessage(Greeting request) { var header = new MessageHeader(); header.Id = request.Id; header.TimeStamp = DateTime.UtcNow; header.Topic = "greeting.topic"; // The target topic to be publish header.MessageType = MessageType.MT_EVENT; var body = new MessageBody(JsonSerializer.Serialize(request)); return new Message(header, body); } public Greeting MapToRequest(Message message) { return JsonSerializer.Deserialize(message.Body.Bytes)!; } } Request Handler Processes incoming messages: public class GreetingHandler(ILogger logger) : RequestHandler { public override Greeting Handle(Greeting command) { logger.LogInformation("Hello {Name}", command.Name); return base.Handle(command); } } Configuring Brighter with RabbitMQ 1. Connection Setup Define RabbitMQ connection details: var connection = new RmqMessagingGatewayConnection { AmpqUri = new AmqpUriSpecification(new Uri("amqp://guest:guest@localhost:5672")), Exchange = new Exchange("paramore.brighter.exchange"), }; 2. RabbitMQ Subscription Subscribe to a queue/topic: .AddServiceActivator(opt => { opt.Subscriptions = [ new RmqSubscription( new SubscriptionName("kafka.greeting.subscription"), new ChannelName("greeting.queue"), new RoutingKey("greeting.topic"), makeChannels: OnMissingChannel.Create ), ]; opt.ChannelFactory = new ChannelFactory( new RmqMessageConsumerFactory(connection) ); }) 3. RabbitMQ Producer Configuration Publish events to a topic: .UseExternalBus(new RmqProducerRegistryFactory(connection, new[] { new RmqPublication { Topic = new RoutingKey("greeting.topic"), MakeChannels = OnMissingChannel.Create } }).Create()); Best Practices Dead Letter Queues (DLQs): Configure DLQs in RabbitMQ to handle poisoned messages. Use deadLetterChannelName and deadLetterRoutingKey in your queue declarations. Monitoring: Use RabbitMQ’s management plugin to track queue health and performance. Error Handling: Implement retries and circuit breakers to handle transient failures (Brighter has retry and circuit breakers via attributes, I'll show it in other article). Conclusion Integrating Brighter with RabbitMQ enables robust, scalable messaging in .NET applications. By leveraging RabbitMQ’s AMQP protocol and Brighter’s abstraction layer, you can: Decouple services with publish-subscribe patterns. Ensure message ordering and reliability. Simplify error handling with DLQs and retries. For production use, validate RabbitMQ configurations against Brighter’s latest documentation, as features like message prioritization or delayed exchanges may evolve. Reference Full code: GitHub Repository Brighter + RabbitMQ

May 12, 2025 - 09:29
 0
Brighter and RabbitMQ: How to setup and use Brighter with RabbitMQ

Introduction to RabbitMQ

RabbitMQ is one of the most widely used message brokers, implementing the Advanced Message Queuing Protocol (AMQP) to ensure reliable message delivery. Built on the Erlang programming language, it offers high scalability and fault tolerance, making it ideal for distributed systems. RabbitMQ acts as an intermediary that accepts messages from producers and delivers them to consumers, decoupling services in a microservices architecture.

Requirement

Brighter Recap

Before continuing about AWS SNS/SQS configuration, let's recap what we already know about Brighter.

Request (Command/Event)

Define messages using IRequest:

public class Greeting() : Event(Guid.NewGuid())
{
    public string Name { get; set; } = string.Empty;
}
  • Commands: Single-recipient operations (e.g., SendEmail).
  • Events: Broadcast notifications (e.g., OrderShipped).

Message Mapper

Translates between Brighter messages and your app objects:

public class GreetingMapper : IAmAMessageMapper<Greeting>
{
    public Message MapToMessage(Greeting request)
    {
        var header = new MessageHeader();
        header.Id = request.Id; 
        header.TimeStamp = DateTime.UtcNow;
        header.Topic = "greeting.topic"; // The target topic to be publish
        header.MessageType = MessageType.MT_EVENT;

        var body = new MessageBody(JsonSerializer.Serialize(request));
        return new Message(header, body);
    }

    public Greeting MapToRequest(Message message)
    {
        return JsonSerializer.Deserialize<Greeting>(message.Body.Bytes)!;
    }
}

Request Handler

Processes incoming messages:

public class GreetingHandler(ILogger<GreetingHandler> logger) : RequestHandler<Greeting>
{
    public override Greeting Handle(Greeting command)
    {
        logger.LogInformation("Hello {Name}", command.Name);
        return base.Handle(command);
    }
}

Configuring Brighter with RabbitMQ

1. Connection Setup

Define RabbitMQ connection details:

var connection = new RmqMessagingGatewayConnection
{
    AmpqUri = new AmqpUriSpecification(new Uri("amqp://guest:guest@localhost:5672")),
    Exchange = new Exchange("paramore.brighter.exchange"),
};

2. RabbitMQ Subscription

Subscribe to a queue/topic:

 .AddServiceActivator(opt =>
{
    opt.Subscriptions = [
       new RmqSubscription<Greeting>(
           new SubscriptionName("kafka.greeting.subscription"),
           new ChannelName("greeting.queue"),
           new RoutingKey("greeting.topic"),
           makeChannels: OnMissingChannel.Create
       ),
    ];

    opt.ChannelFactory = new ChannelFactory(
                        new RmqMessageConsumerFactory(connection)
                    );
})

3. RabbitMQ Producer Configuration

Publish events to a topic:

.UseExternalBus(new RmqProducerRegistryFactory(connection, new[]
            {
                new RmqPublication
                {
                    Topic = new RoutingKey("greeting.topic"),
                    MakeChannels = OnMissingChannel.Create
                }
            }).Create());

Best Practices

  • Dead Letter Queues (DLQs): Configure DLQs in RabbitMQ to handle poisoned messages. Use deadLetterChannelName and deadLetterRoutingKey in your queue declarations.
  • Monitoring: Use RabbitMQ’s management plugin to track queue health and performance.
  • Error Handling: Implement retries and circuit breakers to handle transient failures (Brighter has retry and circuit breakers via attributes, I'll show it in other article).

Conclusion

Integrating Brighter with RabbitMQ enables robust, scalable messaging in .NET applications. By leveraging RabbitMQ’s AMQP protocol and Brighter’s abstraction layer, you can:

  • Decouple services with publish-subscribe patterns.
  • Ensure message ordering and reliability.
  • Simplify error handling with DLQs and retries.

For production use, validate RabbitMQ configurations against Brighter’s latest documentation, as features like message prioritization or delayed exchanges may evolve.

Reference