Please read Part 1 RabbitMQ Best Practice for general best practice and dos and don’ts tips for RabbtitMQ.
Don’t open and close connections or channels repeatedly
Have long lived connections if possible, and use channels for each task. The handshake process for an AMQP connection is quite complex and requires at least 7 TCP packets (more if TLS is used). Channels can be opened and closed more frequently if needed. Even channels should be long-lived if possible, e.g., reuse the same channel per thread for publishing. Don’t open a channel each time you are publishing. If you can't have long lived connections, then make sure to gracefully close the connection Best practice is to reuse connections and multiplex a connection between threads with channels.
- AMQP connections: 7 TCP packages
- AMQP channel: 2 TCP packages
- AMQP publish: 1 TCP package (more for larger messages)
- AMQP close channel: 2 TCP packages
- AMQP close connection: 2 TCP packages
- Total 14-19 packages (+ Acks)
Don’t use too many connections or channels
Try to keep connection/channel count low. Use separate connections to publish and consume. You should ideally only have one connection per process, and then use a channel per thread in your application.
- Reuse connections
- 1 connection for publishing
- 1 connection for consuming
Don’t share channels between threads
You should make sure that you don’t share channels between threads as most clients don’t make channels thread-safe (because it would have a serious negative impact on performance).
Don't have too large queues
Short queues are the fastest. When a queue is empty, and it has consumers ready to receive messages, then as soon as a message is received by the queue, it goes straight out to the consumer.
Many messages in a queue can put a heavy load on RAM usage. When this happens, RabbitMQ will start flushing (page out) messages to disk to free up RAM, and when that happens queueing speeds will deteriorate.
Problems with long queues
- Small messages embedded in the queue index
- Take a long time to sync between nodes
- Time-consuming to start a server with lots of messages
- RabbitMQ management interface collects and stores stats for all queues
Don't use old RabbitMQ/Erlang versions or RabbitMQ clients/libraries
Stay up-to-date with the latest stable versions of RabbitMQ and Erlang. Make sure that you are using the latest recommended version of client libraries.
Don't have an unlimited prefetch value
A typical mistake is to have an unlimited prefetch, where one client receives all messages and runs out of memory and crashes, and then all messages are re-delivered again. More information about prefetch can be found here.
Don't ignore lazy queues
Use lazy queues to get predictable performance (or if you have large queues).
With lazy queues, the messages go straight to disk and thereby the RAM usage is minimized, but throughput will be lower.
Lazy queues create a more stable cluster, with more predictable performance. Your messages will not, without a warning, get flushed to disk.
Limit queue size with TTL or max-length - if possible
Applications that often get hit by spikes of messages, and where throughput is more important than anything else, set a max-length on the queue. This will keep the queue short by discarding messages from the head of the queues so that it’s never larger than the max-length setting.
Use multiple queues and consumers
You will achieve better throughput on a multi-core system if you have multiple queues and consumers. You will achieve optimal throughput if you have as many queues as cores on the underlying node(s).
Persistent messages and durable queues for a message to survive
a server restart
If you cannot afford to lose any messages, make sure that your queue is declared as “durable” and your messages are sent with delivery mode "persistent" (delivery_mode=2).
For high throughput send transient messages to non-lazy queues.
Split your queues over different cores
Queue performance is limited to one CPU core. You will, therefore, get better performance if you split your queues into different cores, and also into different nodes if you have a RabbitMQ cluster.
Consume (push), don’t poll (pull) for messages
Make sure that your consumer consumes messages from the queue, instead of using basic get.
Missing HA policy while creating a new vhost on a cluster
When you create a new vhost on a cluster - don't forget to enable a HA-policy for that vhost (even if you don’t have a HA setup, you will need it for plan changes). Messages will not be synced between nodes without an HA-policy.