Load Balancing with Stomp and ActiveMessaging 14 Apr 10
Inevitably with modern distributed software architecture you’re going to end up talking to a message queue at some point. We’ve been using ActiveMQ as the message broker, STOMP as the message protocol of choice and the ActiveMessaging gem so that we can talk to the message broker from Rails.
ActiveMessaging is a great piece of code, but at first glance it appears to have a couple of wrinkles
- The standard configuration doesn’t support load balancing (so that you can talk to another broker if your normal one isn’t responding).
- The queues and topics you want to speak to are defined at class level – which is a problem if you want the queues to be dynamically defined based upon data values.
But thanks to Ruby, YAML and a bit of lateral thinking you can get around these issues.
ActiveMessaging uses the Stomp Gem under the hood, and that can do load balancing by itself. So all you have to do is get ActiveMessaging to pass the relevant incantations down to the Stomp Gem – intact. And you do that with a bit of fancy YAML. The trick is to add your host configurations to the login configuration entry in hash format like this:
production:
adapter: stomp
login:
:randomize: true
:hosts:
- :login: myloginid1
:passcode: mypassword1
:host: broker-host-1.somedomain.co.uk
- :login: myloginid2
:passcode: mypassword2
:host: broker-host-2.somedomain.co.uk
The Stomp Connection class checks login to see if it is a hash and if it is uses that in preference to anything else. You can setup anything Stomp understands within that Hash. Check the class code for details.
The beauty of this approach is that it is entirely in the configuration. Your Rails code doesn’t need to know about it. The reconnection happens automatically in the background.
I’ve used an observer class within Rails to handle the message sending. It watches a model and sends messages when stuff is created and updated – nicely separating the concerns. But I wanted to talk to different queues depending upon what was in the model. So the standard ActiveMessaging::MessageSender approach didn’t seem appropriate.
After a bit of digging around it turns out that you can get hold of the broker connection directly rather than going via the Gateway.
client = ActiveMessaging::Gateway.connection
Then you can send to any queue you like, not just the ones defined up front in messaging.rb:
client.send("/queue/#{some_variable}", body, headers)
This is a lower level connection and you lose the filter chains and some error checking. However if you need it, it’s there.

3 years ago Craig R Webster said:
SMQueue is also a message-broker abstraction layer that supports failover for ActiveMQ:
http://barkingiguana.com/2009/01/04/using-smqueue-with-message-queues-that-failover
The load balancing just now only supports two hosts – it’d be great to extend that to support an arbitrary number of hosts and ideally I’d like to make sure failover works in an adapter independent manner so we can failover on RabbitMQ/AMQP, Ejabberd/XMPP or whatever the message broker/protocol is.