RabbitMQ Federation Plugin
Introduction
The RabbitMQ Federation Plugin is a powerful extension that allows you to connect multiple RabbitMQ brokers (servers) across different locations, data centers, or network segments. Unlike clustering, which requires brokers to be on the same network with low latency, federation creates looser connections optimized for high-latency or unreliable networks.
Federation enables message producers in one location to seamlessly publish messages that can be consumed by subscribers in different geographic locations, without requiring consumers to connect to distant brokers.
What is Federation?
Federation creates links between brokers where messages published to an exchange in one broker can be automatically transferred to exchanges in other brokers. Similarly, queues in one broker can receive messages from queues in other brokers.
Think of federation as a system of "upstream" and "downstream" relationships:
Federation vs. Clustering
Before diving deeper, let's understand how federation differs from RabbitMQ clustering:
Feature | Federation | Clustering |
---|---|---|
Network requirements | Works across WANs, firewalls | Requires LAN, low latency |
Topology | Selective message sharing | All definitions shared |
Failure handling | Independent brokers | Cluster-wide impact |
Message replication | Only selected messages | Complete replication |
Setup complexity | Simpler to configure | More complex |
Enabling the Federation Plugin
The federation plugin is included in the RabbitMQ distribution but needs to be enabled:
# Enable the plugin
rabbitmq-plugins enable rabbitmq_federation
# Also enable the management UI for federation
rabbitmq-plugins enable rabbitmq_federation_management
After enabling, restart your RabbitMQ server to apply the changes.
Configuring Federation
Federation configuration involves a few key steps:
Step 1: Define an Upstream
First, define which remote broker(s) you want to connect to. This is done by creating an "upstream" configuration:
# Using rabbitmqctl
rabbitmqctl set_parameter federation-upstream my-upstream \
'{"uri":"amqp://guest:guest@remote-host:5672", \
"ack-mode":"on-confirm", \
"prefetch-count":1000}'
Or through the management UI:
- Go to Admin > Federation Upstreams
- Click "Add a new upstream"
- Fill in the form with your upstream details
Step 2: Set Up a Federation Policy
Next, create a policy that determines which exchanges or queues should be federated:
# Federation policy for exchanges
rabbitmqctl set_policy --apply-to exchanges \
exchange-federation "^federated\." \
'{"federation-upstream-set":"all"}'
# Federation policy for queues
rabbitmqctl set_policy --apply-to queues \
queue-federation "^federated\." \
'{"federation-upstream-set":"all"}'
This example policy federates all exchanges and queues whose names start with "federated.".
Exchange Federation Example
Let's see a practical example of exchange federation using Python with the Pika library:
# Producer code (on upstream broker)
import pika
# Connect to the local RabbitMQ server
connection = pika.BlockingConnection(
pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
# Create a federated exchange
channel.exchange_declare(exchange='federated.topic',
exchange_type='topic',
durable=True)
# Publish a message
routing_key = 'user.created'
message = '{"id": 123, "name": "John Doe"}'
channel.basic_publish(
exchange='federated.topic',
routing_key=routing_key,
body=message,
properties=pika.BasicProperties(
content_type='application/json',
delivery_mode=2 # make message persistent
))
print(f" [x] Sent '{routing_key}': {message}")
connection.close()
# Consumer code (on downstream broker)
import pika, json
# Connect to the local broker (which receives federated messages)
connection = pika.BlockingConnection(
pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
# Make sure the exchange exists (will receive from upstream)
channel.exchange_declare(exchange='federated.topic',
exchange_type='topic',
durable=True)
# Create a queue and bind it
result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue
channel.queue_bind(
exchange='federated.topic',
queue=queue_name,
routing_key='user.#') # Subscribe to all user events
print(' [*] Waiting for messages. To exit press CTRL+C')
def callback(ch, method, properties, body):
data = json.loads(body)
print(f" [x] Received {method.routing_key}: {data}")
ch.basic_ack(delivery_tag=method.delivery_tag)
channel.basic_consume(
queue=queue_name,
on_message_callback=callback)
channel.start_consuming()
In this example:
- The producer publishes to a topic exchange named 'federated.topic' on the upstream broker
- The federation plugin automatically forwards messages to the same-named exchange on downstream brokers
- Consumers on the downstream broker receive messages as if they were published locally
Queue Federation
Queue federation allows messages to be moved from queues in one broker to queues in another broker:
The downstream queue acts as a consumer of the upstream queue, pulling messages across the federation link.
Queue Federation Example
Set up a federated queue:
# On the downstream broker
rabbitmqctl set_parameter federation-upstream upstream-broker \
'{"uri":"amqp://guest:guest@upstream-host:5672"}'
rabbitmqctl set_policy --apply-to queues queue-federation \
"^federated\." '{"federation-upstream":"upstream-broker"}'
Now, any queue matching the pattern federated.*
will pull messages from its counterpart on the upstream broker.
Federation Parameters and Tuning
Federation offers several parameters for fine-tuning:
Parameter | Description | Default |
---|---|---|
prefetch-count | Maximum number of unacknowledged messages | 1000 |
reconnect-delay | Time in seconds to wait after failed connection | 5 |
ack-mode | Acknowledgment mode (on-confirm, on-publish, no-ack) | no-ack |
trust-user-id | Whether to trust user IDs from upstream | false |
max-hops | Maximum number of federation hops for a message | 1 |
Example of setting multiple parameters:
rabbitmqctl set_parameter federation-upstream production-broker \
'{"uri":"amqp://user:pass@prod-host:5672", \
"prefetch-count":2000, \
"reconnect-delay":10, \
"ack-mode":"on-confirm", \
"max-hops":2}'
Multi-Datacenter Topology Example
Let's consider a real-world scenario where you have three data centers and want to set up a hub-and-spoke federation model:
Implementation steps:
-
On DC2 and DC3, configure DC1 as an upstream:
bashrabbitmqctl set_parameter federation-upstream primary-dc \
'{"uri":"amqp://user:pass@dc1-host:5672"}' -
Set up federation policies:
bash# On DC2 and DC3
rabbitmqctl set_policy --apply-to exchanges \
federate-global "^events\.global$" \
'{"federation-upstream":"primary-dc"}' -
Configure local message routing:
python# On each DC, set up binding from global to local exchange
channel.exchange_declare(exchange='events.local',
exchange_type='topic',
durable=True)
channel.exchange_bind(
destination='events.local',
source='events.global',
routing_key='#.local.#')
This setup allows global events to flow from DC1 to all data centers, while each data center can also handle local-only events.
Monitoring Federation Status
You can monitor federation links through the RabbitMQ Management UI or via HTTP API:
- In the Management UI, go to "Admin" > "Federation Status"
- Via HTTP API:
GET /api/federation-links
The output includes information such as:
- Status (running, starting, etc.)
- Message rates (messages/sec)
- Number of messages in transit
- Last time the link was active
Troubleshooting Federation
Common federation issues and their solutions:
-
Links not establishing
- Check network connectivity between brokers
- Verify credentials in the URI
- Ensure the federation plugin is enabled on both brokers
-
Messages not flowing
- Check that your federation policy pattern matches your exchange/queue names
- Verify that bindings exist on the downstream broker
- Check the upstream exchange type (topic, fanout, etc.) is compatible
-
Poor performance
- Increase
prefetch-count
for higher throughput - Consider using
on-publish
acknowledgment mode for lower latency - If messages are large, consider compression or message optimization
- Increase
Summary
The RabbitMQ Federation Plugin provides a flexible, robust way to connect multiple RabbitMQ brokers across different locations. Unlike clustering, federation is designed for high-latency, unreliable networks, making it ideal for geographically distributed systems.
Key takeaways:
- Federation connects brokers across WANs and different networks
- It selectively shares messages between brokers without full replication
- Configuration involves setting up upstreams and policies
- Both exchanges and queues can be federated
- Federation is simpler to set up than clustering for distributed deployments
Exercise: Setting Up a Simple Federation
Try this exercise to practice federation:
- Set up two RabbitMQ instances (can be on the same machine with different ports)
- Enable the federation plugin on both
- Configure the second instance to federate from the first
- Create a federated exchange and test publishing/consuming across the federation link
- Monitor the federation status in the management UI
Additional Resources
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)