OpenStack Series Chapter5: Introducing Component Communiation---RabbitMQ
Introduction and Overview of RabbitMQ
As we discussed before in the last Chapter, OpenStack is highly modular—each
function (like Nova, Neutron, Cinder, etc.) operates as an independent service.
All services depend on two back end functions:
Database (MariaDB)
Database is used to store the persistent data of each OpenStack component.
Message Broker (RabbitMQ)
Message Broker is used to support the communication between each component. Any message broker if only supports
AMQP
(Advanced Message Queueing Protocol) protocol could be used as a back end.In OpenStack here, we use
RabbitMQ
as the message broker.
Some common RabbitMQ terms and definitions
Term | Description |
---|---|
Binding | The key or filter parameter used to route from an exchange to a queue. |
Consumer | An application that uses the received messages. |
Exchange | Routes producer-published messages to queues using message metadata. |
Publisher/Producer | Applications that publish messages. |
Queue | Stores messages until consumed by an application. |
Routing key | Producer-specified message metadata used by the exchange for message routing. |
Vhost | A logical division of a RabbitMQ instance, used to segregate applications, queues, and exchanges. |
Binding
Binding
determines the connection between thequeue
and theexchange
.Consumer
Consumer
is the application or server side to receive messages, here in OpenStack, it represents those service components.Exchange
Exchange
is like anallocation center
. Based onBinding
the rule, it will route the message to the corresponding queue.(routing key matches the binding key)Publisher/Produce
Publisher/Produce
is the application or client side to send messages, here in OpenStack, it represents those service components.Queue
Queue
is a temporary space to storage the request messages, until customers fetch messages here.Routing Key
Routing Key
is the information produce send with the message, for specifying the destination, the matched queue that the message should be routed to.(routing key matches the binding key)Vhost
Vhost
provides theisolated
environment for each project, it just likes anamespace
.
RabbitMQ Message Broker Exchange Concepts
The exchange’s interaction with a queue is based on the match between the routing key included in the message
and the binding key associated with the queue
on the related exchange.
This is called the Binding
rule.
Different kinds of exchange determine the match mode of routing key
and binding key
.
Messaging Patterns in RabbitMQ
Exchange
,Binding
andQueue
are combined in patterns.
Pattern Name | Description | One-to-Many | Callback |
---|---|---|---|
Work Queue | A single queue with multiple consumers, messages are distributed in round-robin | ❌ | ❌ |
Pub/Sub | Each consumer has its own queue and receives all messages | ✅ | ❌ |
Routing | Exact match on routing key | ✅ | ❌ |
Topic | Fuzzy match on routing key (wildcards allowed) | ✅ | ❌ |
Header | Routing based on headers | ✅ | ❌ |
RPC | Request and response messaging (Remote Procedure Call) | ❌ (point-to-point) | ✅ |
1. Publish/Subscribe
Multiple consumers receive the same message.
Characteristics:
- Uses a
fanout
exchange - Messages are broadcast to all bound queues
- Each consumer has its own queue, isolated from others
Use Cases:
- Broadcasting notifications
- Log collection
- Multiple subsystems responding to events simultaneously
2. Routing
Messages are delivered based on an exact match of the routing key.
Characteristics:
- Uses a
direct
exchange - Queues are bound with binding keys that exactly match routing keys
- Multiple queues can be bound with different keys
Use Cases:
- Processing different types of tasks in multiple modules
- Log levels separation (e.g., error, info, debug)
3. Topic
Routing key supports pattern matching with wildcards.
Characteristics:
- Uses a
topic
exchange - Supports wildcards
*
and#
- More flexible and complex routing logic
Use Cases:
- Microservices event bus
- Logging systems with hierarchical logs like
logs.system.error
,logs.user.info
4. Header
Routing based on message header attributes.
Characteristics:
- Uses a
headers
exchange - Does not use routing keys, but matches based on header attributes
Use Cases:
- Advanced routing policies
- Attribute-driven message delivery (e.g., region=us, format=json)
5. Work Queue
Multiple consumers share a single queue, and each message is delivered to only one consumer.
Produce sends the message with the routing key to the exchange
(only specify the exchange name), then the exchange will based on its types to determine which queue shoud be routed to. Then, customers subscribe the queue to receive the message from produce.
Many customers subscribe the same queue, even if there is no exchange, queues could aslo hand out work to different multiple customers. The work queue distributes requests in chronological order and follow the rule FIFO(first in first out) in the round-robin
way.
Characteristics:
- Typically uses a
direct or default
exchange - Multiple consumers compete for messages from the same queue
- Enables load balancing (the idle consumer takes the message)
Use Cases:
- Background task processing
- Batch jobs
- Data import, etc.
6. RPC (Remote Procedure Call)
Client sends a request, server processes it and replies back (pseudo-synchronous).
Characteristics:
- Uses a
direct
exchange for thecallback
andtopic
exchange for sending - Messages contain
reply_to
andcorrelation_id
properties - Responses are sent back to a specified temporary queue
Use Cases:
- RPC calls between OpenStack components
- Asynchronous task tracking in Celery
reply_to
What is reply_to
?
Meaning: It tells the server “after processing, send the result to which queue”.
Type: A string representing the name of the callback queue (reply queue).
Purpose: Allows the client to receive the response message.
Analogy: It’s like sending a parcel and writing “please send the result back to my office address” — this address is the reply_to
.
correlation_id
What is correlation_id
?
Meaning: A unique identifier (ID) that establishes the correspondence between request and response.
Type: Usually a UUID or any unique string.
Purpose: When the client sends multiple requests, it can use the correlation_id
to identify which response corresponds to which request.
Analogy: You send multiple questions (letters), each labelled “Question 1”, “Question 2”, etc. The reply includes the same label, so you know which answer matches which question.
Exchanges
Direct
Direct Exchange: The routing keys are matched against a simple string, like “sales.*“. This means that any message with an exact binding key will be routed to this queue (and vice versa). “Direct” exchange type is used when you want messages sent directly from one application/service into another.
In other words, the routing key must be the same as
the binding key, one-to-one.
E.g. taskC_create
message is routed to taskC_queue
queue.
Topic
Topic Exchange: This type of exchange functions like a “fuzzy match”
. The routing key of a message and the binding key of a queue can include wildcards (* and #)
, allowing for more flexible matching. The *
wildcard matches a single word
, while #
matches multiple words
.
E.g. A message can be delivered to one or more queues at the same time. Only compute tasks
are routed to the queue named compute_tasks
, while all tasks
, including compute ones, are routed to the queue named all_tasks
.
Fanout
Fanout Exchange: It is like a “broadcast”
. It sends messages to all bound queues
, regardless of the routing key
. Simply put, “if it’s bound, it gets the message”. For example, in a logging system, all queues bound to the exchange will receive the message.
Headers
Headers: This exchange type makes use of the message headers to perform the match against the binding arguments of the queue. This is similar to a topic exchange except that there can be multiple key-value headers, and the queue can be matched against any or all. And headers ignore the routing key
at all.
Rabbitmq common command
Check the report summary
1 | ()[root@controller0 /]# rabbitmqctl report |
List users
1 | ()[root@controller0 /]# rabbitmqctl list_users |
Create users
1 | ()[root@controller0 /]# rabbitmqctl add_user shy shypassword |
Allocate the permission
configure: Define the resources that the user could configure.
write: Define the resources that the user could write.
read: Define the resources that the user could read.
1 | ()[root@controller0 /]# rabbitmqctl set_permissions shy '.*' '.*' '.*' |
Add the tag to users
1 | ()[root@controller0 /]# rabbitmqctl set_user_tags shy administrator |
List all exchanges
1 | ()[root@controller0 /]# rabbitmqctl list_exchanges |
The last one is an implicit direct
type exchange.
Its name is an empty
string “”.
Every queue is automatically bound to it with a binding key
that matches the queue’s name
.
List all available queues
1 | ()[root@controller0 /]# rabbitmqctl list_queues |
List all customers
1 | ()[root@controller0 /]# rabbitmqctl list_consumers |
Trace on the RabbitMQ message
This feature can be used to track all messages flowing through the system, whether incoming or outgoing. In other words, it acts like a supervisor, logging every message in motion. This capability is based on the firehose
mechanism.
The name firehose comes from its function—it behaves like a firehose, spraying out
all messages so you can see each one passing through. This feature is very useful during development and debugging, but as it records all messages, it may impact performance.
Enable the trace
1 | rabbitmqctl trace_on |
Once enabled, all messages entering the RabbitMQ system are copied to a special exchange called amq.rabbitmq.trace
. This allows you to observe the entire message flow within that exchange, which is particularly useful for debugging and monitoring
.
Performance impact: Enabling the Firehose Tracer
increases system load
, as it must handle and replicate every message. Therefore, it is recommended to enable it only when debugging is necessary, and todisable it promptly once debugging is complete
.Monitoring amq.rabbitmq.trace: After enabling tracing, you can monitor system activity by inspecting the messages in the
amq.rabbitmq.trace exchange
. This exchange contains copies of all messages, making it easier to analyse system behaviour.
Disable the trace
1 | rabbitmqctl trace_off |