We have been hosting RabbitMQ for many years, and we have probably seen way more configuration mistakes than anybody else. Here is a list, that will help you avoid common RabbitMQ mistake!
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 repeatedlyHave 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 packagesAMQP channel: 2 TCP packagesAMQP publish: 1 TCP package (more for larger messages)AMQP close channel: 2 TCP packagesAMQP close connection: 2 TCP packagesTotal 14-19 packages (+ Acks)
- Don’t use too many connections or channelsTry 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 connections1 connection for publishing1 connection for consuming
- Don’t share channels between threadsYou 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 queuesShort 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 queuesSmall messages embedded in the queue indexTake a long time to sync between nodesTime-consuming to start a server with lots of messagesRabbitMQ management interface collects and stores stats for all queues
- Don't use old RabbitMQ/Erlang versions or RabbitMQ clients/librariesStay 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 valueA 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 queuesUse 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 possibleApplications 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 consumersYou 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 restartIf 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 coresQueue 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 messagesMake sure that your consumer consumes messages from the queue, instead of using basic get.
- Missing HA policy while creating a new vhost on a clusterWhen 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.