RabbitMQ With ASP.NET Core - Microservice Communication With MassTransit

This article will show Microservice Communication using RabbitMQ with ASP.NET Core. We will learn how to enable communication between Microservices using RabbitMQ and MassTransit.

We will be using MassTransit Helpers to publish/receive messages from our RabbitMQ server,

What is a Message Broker?

Before going to RabbitMQ, we will see about Message Broker. Message Broker's main responsibility is to broker messages between publisher and subscribers.

Once a message broker receives a message from the producer, it routes the message to a subscriber. The message broker pattern is one of the most useful patterns when it comes to decoupling microservices.

  • Producer: An application responsible for sending messages.
  • Consumer: An application responsible for messages.
  • Queue: Storage where messages are stored

What is RabbitMQ?

RabbitMQ is one of the most widely used open-source message Broker services. It basically gives your applications a common platform for sending and receiving messages. This ensures that our messages (data) are never lost and successfully receivedby consumers and it supports various messaging protocols.

Advantages Of RabbitMQ

There are some reasons why using a queue instead of directly sending data is better,

  • Higher availability and better error handling
  • Better scalability
  • Extremely lightweight and very easy to deploy
  • Share data with whoever wants/needs it
  • Better user experience due to asynchronous processing

Demonstration of RabbitMQ setup

RabbitMQ

A simple demonstration of RabbitMQ setup. In case, any of the consumers is offline for some time, messages are still in RabbitMQ waiting for consumers to come online and receive messages.

Protocol supported

RabbitMQ supports multiple protocols

  • AMQP 0–9–1: RabbitMQ was originally developed to AMQP 0–9–1. AMQP 0–9–1 is a binary protocol and defines quite strong messaging semantics.
  • STOMP: is a text-based messaging protocol.
  • MQTT: Binary protocol focusing mainly on Publish/Subscribe scenarios.
  • AMOP 1.0
  • HTTP and WebSocket: While HTTP is not a messaging protocol, RabbitMQ can transmit messages over HTTP

What is MassTransit

MassTransit essentially helps developers route messages over Messaging Service Buses, with support for RabbitMQ. MassTransit does not have a specific implementation. It works like an interface, an abstraction over the whole message bus concept.

Setting Up The Environment

For installing RabbitMQ, there are multiple approaches, I would recommend Approach 1 i.e., by installing via docker images,

Approach 1

Install ErLang and RabbitMQ on your local machine,

  • ErLang
  • RabbitMQ

Approach 2

Or run docker rabbitMQ with a management web console.

docker run -d --hostname my-rabbit --name some-rabbit -p 15672:15672 -p 5672:5672 rabbitmq:3-management

To enable the RabbitMQ management plugin- Dashboard

To activate the RabbitMQ management dashboard, run the below command in the command prompt with the administrator.

cd C:\Program Files\RabbitMQ Server\rabbitmq_server-3.8.17\sbin
rabbitmq-plugins enable rabbitmq_management
net stop RabbitMQ
net start RabbitMQ

Now navigate to http://localhost:15672, where you can find the management dashboard of RabbitMQ running.

Login page of RabbitMQ

The default user id and password for management is guest/guest.

Getting Started

Nuget library is used in the application.

Install-Package MassTransit
Install-Package MassTransit.AspNetCore
Install-Package MassTransit.RabbitMQ

CloneSource codeand you can see the project structure via Solution Explorer. We walk through the code.

Solution explorer

CrossCuttingLayer

This is a common class library for all the applications. Here we have Model (i.e., Todo class) and Constant (For RabbitMQ configuration).

Below is the code snippet for the TodoandConstantclasses.

Todo.cs

using System;
namespace CrossCuttingLayer
{
    public class Todo
    {
        public string Id { get; set; }
        public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
        public string TaskDescription { get; set; }
        public bool IsCompleted { get; set; }
    }

}

RabbitMqConsts.cs

public class RabbitMqConsts
{
    public const string RabbitMqRootUri = "rabbitmq://localhost";
    public const string RabbitMqUri = "rabbitmq://localhost/todoQueue";
    public const string UserName = "guest";
    public const string Password = "guest";
    public const string NotificationServiceQueue = "notification.service";
}

Publisher class library

We will configure MassTransit in a startup.cs file in our Asp.net Core Web API application.

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddMassTransit(x =>
    {
        x.AddBus(provider => Bus.Factory.CreateUsingRabbitMq(config =>
        {
            config.Host(new Uri(RabbitMqConsts.RabbitMqRootUri), h =>
            {
                h.Username(RabbitMqConsts.UserName);
                h.Password(RabbitMqConsts.Password);
            });
        }));
    });
    services.AddMassTransitHostedService();
    services.AddControllers();
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "Microservice.Todo.Publisher", Version = "v1" });
    });
}

And in our publisher controller, we will create a post method to publish a message.

TodoController.cs

[HttpPost]
public async Task<IActionResult> CreateTicket(Todo todoModel)
{
    if (todoModel is not null)
    {
        Uri uri = new Uri(RabbitMqConsts.RabbitMqUri);
        var endPoint = await _bus.GetSendEndpoint(uri);
        await endPoint.Send(todoModel);
        return Ok();
    }
    return BadRequest();
}

Notification class library

For testing, we will see a console application. In the below code snippet we will register for consumption in the Program.cs file and write consume method in TodoConsumerNotification.cs file to display messages.

static void Main(string[] args)
{
    Console.Title = "Notification";
    var bus = Bus.Factory.CreateUsingRabbitMq(cfg =>
    {
        cfg.Host(new Uri(RabbitMqConsts.RabbitMqRootUri), h =>
        {
            h.Username(RabbitMqConsts.UserName);
            h.Password(RabbitMqConsts.Password);
        });
        cfg.ReceiveEndpoint("todoQueue", ep =>
        {
            ep.PrefetchCount = 16;
            ep.UseMessageRetry(r => r.Interval(2, 100));
            ep.Consumer<TodoConsumerNotification>();
        });

    });
    bus.StartAsync();
    Console.WriteLine("Listening for Todo registered events.. Press enter to exit");
    Console.ReadLine();
    bus.StopAsync();
}
public class TodoConsumerNotification : IConsumer<Todo>
{
    public async Task Consume(ConsumeContext<Todo> context)
    {
        await Console.Out.WriteLineAsync($"Notification sent: todo id {context.Message.Id}");
    }
}

Testing our application

Scenario 1

Keeping Publisher and Consumer/Notification running as Multiple startup projects.

Startup project

Call post methodAPI/todo via Swagger like the below image.

Parameters

Output

Notification

Scenario 2

Keeping Publisher set as a start-up project and Consumer/Notification running offline.

Call post method API/todo via Swagger like the below image,

Post

You can see that our Queue has 1 new Message Ready which does not deliver yet. It will keep the messages in memory till a consumer is connected.

Overview

Queues

Let’s bring our Consumer online now, and we can see the message is delivered and Queue is 0.

Overview totals

Queues

Summary

In this article, we have gone through Message Brokers, RabbitMQ, Advantages, and Integrating RabbitMQ with ASP.NET Core using MassTransit. We also build a small prototype application to send data over the RabbitMQ Server. Download source code from GitHub