How to work with RabbitMQ in C#

Take advantage of RabbitMQ, an open source, fast message broker to store and retrieve messages in your applications

How to work with RabbitMQ in C#
Toms Baugis (Creative Commons BY or BY-SA)

RabbitMQ is an increasingly popular open source, fast message broker written using Erlang and built on the Open Telecom Platform framework. It implements the Advanced Message Queuing Protocol (AMQP) for exchanging data between processes, applications, and servers. It’s particularly enticing because it is extensible via plug-in support, supports many protocols, and offers high performance, reliability, clustering, and highly available queues.

You can create queues in RabbitMQ by writing code, via the administration user interface, or through PowerShell.

RabbitMQ terms

When working with RabbitMQ, you should be aware of two terms:

  • A queue is a data structure that works on the basis of FIFO (first in first out). In this context, a queue is a large message buffer that can hold data.
  • A producer is the component that produces some data that is pushed to the queue; it sends data to the queue and a consumer is one that consumes the data that is stored in the queue. (The producer-consumer pattern is one of the most widely used patterns in parallel programming.)

Installation and setup

Setting up RabbitMQ is quite simple. Before you install RabbitMQ, you should install Erlang. Download the correct version of Erlang depending on the operating system you are using. Next, download and install RabbitMQ server.

Programming RabbitMQ in C#

Now that you have installed Erlang and RabbitMQ in your system, you need to install the RabbitMQ .Net client to connect to and work with the RabbitMQ service. You can install the RabbitMQ client via the NuGet Package Manager.

Create a new console application in Visual Studio. Next, install the RabbitMQ.Client package via the NuGet Package Manager. Assuming that RabbitMQ server is running locally in your system, the following code snippet can be used to create a connection to RabbitMQ server.

ConnectionFactory connectionFactory = new ConnectionFactory();
IConnection connection = connectionFactory.CreateConnection();

Now suppose RabbitMQ service is running in a remote system. Here's a method that returns you a connection instance to the RabbitMQ service.

public IConnection GetConnection(string hostName, string userName, string password)
        {
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.HostName = hostName;
            connectionFactory.UserName = userName;
            connectionFactory.Password = password;
            return connectionFactory.CreateConnection();
        }

Sending and receiving messages

With the RabbitMQ service running locally in your system, use the following method to send messages to a queue. Note that the connection to the RabbitMQ service has been established using the default settings.

public static void Send(string queue, string data)
        {
            using (IConnection connection = new ConnectionFactory().CreateConnection())
            {
                using (IModel channel = connection.CreateModel())
                {
               channel.QueueDeclare(queue, false, false, false, null);
        channel.BasicPublish(string.Empty, queue, null, Encoding.UTF8.GetBytes(data));
                }
            }
        }

A channel is used to establish a communication with the server to send and receive messages. The messages that would be sent to the queue using this method are not durable — I’ve passed false as the second parameter to the QueueDeclare method. So, the messages sent using this method persist only in the memory and not survive a server restart.

The following method illustrates how you can consume the data previously stored in the queue.

public static void Receive(string queue)
        {
            using (IConnection connection = new ConnectionFactory().CreateConnection())
            {
                using (IModel channel = connection.CreateModel())
                {
               channel.QueueDeclare(queue, false, false, false, null);
               var consumer = new EventingBasicConsumer(channel);
               BasicGetResult result = channel.BasicGet(queue, true);
                    if (result != null)
                    {
                      string data =
                      Encoding.UTF8.GetString(result.Body);
                        Console.WriteLine(data);
                    }
                }
            }
        }

The next code snippet shows how you can call the Send and the Receive methods we created in this post:

static void Main(string[] args)
{
     Send("IDG","Hello World!");
     Receive("IDG");
     Console.ReadLine();
}

Persistence in RabbitMQ

RabbitMQ provides excellent support for persistence. You can have two types of queues: Durable and Non-Durable. A Durable queue has the messages persist on the disk, whereas a Non-Durable queue persists only in memory. So, after a server restart, the messages in Durable queues are available whereas messages in Non-Durable queues are lost.

You can set persistence at three levels: Queue, Exchange and Message.