Inspired by Nanite, a very interesting project by Ezra Zygmuntowicz of EngineYard that uses RabbitMQ and eventmachine-based ruby amqp library by Aman Gupta, I sat down and wrote Rabbitbal, a reverse proxy for Rails (as well as other web frameworks, not necessarily limited to Ruby) on top of RabbitMQ. It’s now available on github at http://github.com/somic/rabbitbal. Rabbitbal code is based on Nanite.
Here are benefits of AMQP-based approach over traditional HTTP-based reverse proxies taken from rabbitbal README file (in no particular order) as I see them.
- Model where workers fetch work as fast as they can (each going at its own pace) in theory should provide more efficient load balancing than a model where proxy assigns work based on certain criteria; methods based on round robin, arbitrary weights or least connections become simply unnecessary.
- RabbitMQ broker implements intelligent failover out of the box - if a web server disconnects before ack'ing, the request will be automagically requeued for another server; all in all, RabbitMQ is way smarter than a bunch of low level TCP connections.
- Enhanced security of actual web servers - servers behind Rabbitbal do not need inbound connectivity, they only need to be able to establish an outgoing connection to RabbitMQ broker(s).
- Rabbitbal does not need to know IPs or have direct connectivity into its web servers (use case: Amazon EC2 without Elastic IPs)
- Using Duplication pattern of RabbitMQ (see Resources below), you could be reading requests and responses off of the same broker in real time (access log aggregation, double-entry book keeping, logging, bot detection)
- You could relatively easily have one request go to more than 1 web server
- Add capacity as often and as much as you like - rabbitbal won't even know
- By slightly readjusting mapping between queues and URIs, you could add or remove capacity per URI if needed
- TCP overhead savings compared with HTTP proxies (AMQP uses persistent TCP connections)