RabbitMQ has become a popular open-source message broker. For anyone new to RabbitMQ, this brief guide gives an overview of RabbitMQ, including how to use it with microservices architecture.
To understand RabbitMQ, we should first start with messaging. Messaging involves the integration of applications so they can work together and exchange information in a decoupled manner. These communications take place by sending messages via a message bus. Implementations of the messaging pattern typically have some core characteristics:
- It is often asynchronous
- Reliable and durable messages
- Support for many message formats
- There is often a recipient involved pulling messages from a queue
While messaging solutions are not new and have been around for a long time, RabbitMQ is one of the most widely used message brokers. It’s a software where queues can be defined, and applications may connect to the queue and transfer a message onto it.
A message can include any information and is stored in the message broker until a receiving application or consumer connects and takes a message off the queue. The consumer then appropriately processes the message. A publisher can add messages to a queue without having to wait for them to be processed.
RabbitMQ and Microservices
RabbitMQ is a good fit for a microservices architecture as it is one of the options for implementing messaging queues. In a microservices architecture you have two ways to communicate between the microservices:
- Synchronous: Microservices call directly to each other, which results in dependency between them.
- Asynchronous: There is a hub or message queue (like RabbitMQ) where you place all requests between the microservices and the corresponding service takes the request, processes it and returns the result to the caller. The microservices are aware of the presence of the hub only.
The message flow in RabbitMQ
The message flow is as follows:
- The producer publishes a message to an exchange (more on exchanges below).
- The exchange receives the message and takes care of its routing.
- The exchange routes the message to the correct queue.
- The messages stay in the queue until a consumer handles them.
- The consumer handles the message. The message gets removed from the queue.
.NET Client library
There are several clients for different languages. The RabbitMQ .NET client is available via Nuget for C# or any other .NET language.
Key API classes
- IConnection: This represents a connection to RabbitMQ using AMQP
- IModel: Represents a channel to the server so that you can create queues and send messages
- ConnectionFactory: Used to construct the IConnection object
- QueueingBasicConsumer: The most common way to receive messages from a queue
The connection abstracts the socket connection and takes care of protocol version negotiation and authentication for us.
After we connect to a broker, we create a channel and we must declare a queue for us to send to. After these steps, we can publish a message to the queue.
Messages are not published directly into a queue. Instead, the producer sends messages to an exchange. Exchanges accept messages from the producer application and route them to messages queues using attributes, bindings and routing keys. A queue needs to be bound to at least one exchange to receive messages.
Four different types of exchanges route messages differently using parameters and bindings setups. Clients can either create exchanges or use the predefined default exchanges.
1 – Direct exchanges
A direct exchange delivers messages to queues based on a message routing key. The routing key is a message attribute added to the message by the producer. A message goes to the queue(s) whose binding key perfectly matches the routing key of the message.
2 – Topic exchanges
Topic exchanges route messages to a queue based on a wildcard match between the routing key and the routing pattern, which is specified by the queue binding. Messages can be routed to one or many queues depending on this wildcard match.
It’s important to note that:
- The routing key must be a list of words, delimited by a period (.).
- The routing patterns may contain an asterisk (“*”) to match a word in a specific position of the routing key. A pound symbol (“#”) indicates a match of zero or more words.
- All messages with a routing key that match the routing pattern are routed to the queue and stay there until the consumer consumes the message.
3 – Fanout exchange
The fanout exchange copies and routes a received message to all queues that are bound to it regardless of routing keys or pattern matching. This exchange can be useful when the same message needs to be sent to one or more queues with consumers who may process the same message in different ways, like in a distributed system where you need to broadcast various state and configuration updates.
4 – Headers exchange
The headers exchange route their messages based on arguments containing headers and optional values. They are very similar to topic exchanges but decide their routes based on header values instead of routing keys.
A unique argument named “x-match,” which can be added in the binding between your exchange and your queue decides if all headers must match or just one. The “x-match” property can have two different values: “any” or “all.”
RabbitMQ is a lightweight, open-source, platform-neutral message broker that provides flexibility in message handling and can be used in a variety of scenarios. It has multiple client libraries for your programming language of choice and a straightforward initial setup which will let you have something up and running quickly.
Although it can be considered as a zero-configuration service once installed, RabbitMQ has many configuration options, which make it very adaptable and able to work in different environments. With the advent of microservices, RabbitMQ is a great choice to handle communication between them asynchronously.
More about this article and the author
In September 2019, Cognizant Softvision celebrated the 5th edition of Programmers’ Week, a global event where more than 140 speakers delivered technical-talks from Argentina, US, Canada, India, Ukraine and Romania. Cristian Piqué, Software Engineer from our Buenos Aires Studio, delivered a presentation about “RabbitMQ for .NET” during the event.