RabbitMQ’s Direct Reply-to feature allows RPC (request/reply) clients to avoid declaring a response queue per request. The feature is extremely powerful because it allows the decoupling benefit of RabbitMQ while gaining a response from the server, but without the overhead of managing a separate queue. Unfortunately, ParkMobile’s backend relies heavily on Go. Our engineers found few examples of where it uses the Direct Reply-to feature with the language. This guide outlines our implementation.
What We Learned
We decided to adopt Direct reply-to because it eliminates many of the headaches associated with managing multiple queues–we all know what a “rabbit hole” that can be. Despite the obvious benefits, however, we did encounter some unexpected pitfalls:
- When looking at the RabbitMQ client, we didn’t see any reply-to queue because according to RabbitMQ it “doesn’t exist”
- Reply-to is generally not fault-tolerant, which means that values will be discarded if a client disconnects after sending a query
After some trial and error, we were able to move past these pitfalls. Our team settled on a few things to look out for in the future:
- Make sure the immediate flag is set to false for all publishing
- The mandatory flag seems to have no baring on whether the message is sent but is likely useful due to rabbit throwing errors if something goes wrong instead of quietly letting messages die
- Start consuming on the “amq.rabbitmq.reply-to” queue before publishing to the other queue
- Once receive a message on the server end, you must reply within that message’s context (i.e. within the for statement per message)
- The Client must set the auto-ack argument to true
- The Server must set the auto-ack argument to false and acknowledge separately
- The Server acknowledge must occur after responding to the reply-to queue
As long as you follow these tips, it should be a breeze to utilize Direct reply-to in Go.
View the full gist here.