public
Description: Using AMQP as a Queuing Backend for Web Apps Should Be Easy
Homepage:
Clone URL: git://github.com/danielsdeleo/qusion.git
qusion /
name age message
file LICENSE Sat Jul 11 13:32:03 -0700 2009 do what thou wilt shall be the whole of the law [danielsdeleo]
file README.rdoc Mon Aug 24 17:29:23 -0700 2009 nitpicking [danielsdeleo]
file Rakefile Sat Jul 11 12:27:46 -0700 2009 initial commit [danielsdeleo]
file init.rb Mon Aug 10 18:55:31 -0700 2009 Follow Rails plugin spec [danielsdeleo]
file install.rb Mon Aug 10 18:55:31 -0700 2009 Follow Rails plugin spec [danielsdeleo]
directory lib/ Mon Aug 10 18:30:37 -0700 2009 Need to specify Qusion::ServerSpy explicitly [danielsdeleo]
directory spec/ Mon Aug 10 18:27:34 -0700 2009 clarify comment [danielsdeleo]
README.rdoc

Qusion

Qusion makes AMQP work with your webserver with no fuss. It’s a simple library/plugin with three features:

  • A set of monkey patches that sets up the required callbacks and/or worker threads so that AMQP will work with Passenger, Thin, or Mongrel. WEBrick, SCGI, and Evented Mongrel are experimentally supported, but not heavily tested.
  • A Channel Pool. You can cause problems for yourself if you create new channels (with MQ.new) for every request. The pool sets up a few of these when your app starts and reuses them.
  • YAML configuration files. If you’re using Rails or Merb, create config/amqp.yml, then fill in the details for development, test, and production. Use Qusion.start() in your environment.rb file and you’re good to go.

Getting Started

First you’ll need the amqp library and a working RabbitMQ installation. This entails:

  • Install Erlang for your platform
  • Install RabbitMQ for your platform
  • (sudo) gem install amqp

Ezmobius has a good walk-through on the readme for nanite if you haven’t done this yet.

Install Qusion

Start by installing Qusion as a plugin:

  script/plugin install git://github.com/danielsdeleo/qusion.git

Next, in your config/environment.rb, add something like:

  # Add eventmachine and amqp gems to config.gem to get config.gem goodies:
  config.gem "eventmachine"
  config.gem "amqp"

  # Start AMQP after rails loads:
  config.after_initialize do
    Qusion.start # no options needed if you're using config/amqp.yml or the default settings.
  end

And that’s it! This will set up AMQP for any ruby app server (tested on mongrel, thin, and passenger). Now, you can use all of AMQP’s functionality as normal. In your controllers or models, you might have:

  MQ.new.queue("my-work-queue").publish("do work, son!")

and it should just work.

Channel Pools

It’s considered bad practice to use MQ.new over and over, as it creates a new AMQP channel, and that creates a new Erlang process in RabbitMQ. Erlang processes are super light weight, but you’ll be wasting them and causing the Erlang VM GC headaches if you create them wantonly. So don’t do that. Instead, use the channel pool provided by Qusion. It’s simple: wherever you’d normally put MQ.new, just replace it with Qusion.channel. Examples:

  # Create a queue:
  Qusion.channel.queue("my-worker-queue")
  # Topics:
  Qusion.channel.topic("my-topic-exchange")
  # etc.

This feature is a bit experimental, so the optimal pool size isn’t known yet. The default is 5. You can change it by adding something like the following to your environment.rb:

  Qusion.channel_pool_size(3)

Configuration

If you’re using rails or merb, you can put your AMQP server details in config/amqp.yml and Qusion will load it when you call Qusion.start(). Example:

  # Put this in config/amqp.yml
  development:
    host: localhost
    port: 5672
    user: guest
    pass: guest
    vhost: /
    timeout: 3600
    logging: false
    ssl: false

  test:
    host: localhost
    port: 5672
    ...

  production:
    host: localhost
    port: 5672
    ...

If you’re too hardcore for rails or merb (maybe you’re using Sinatra or Ramaze), you can still use a YAML config file, but there’s no support for different environments. So do something like this:

  # Tell Qusion where your config file is:
  Qusion.start("/path/to/amqp.yml")

  # Your configuration looks like this:
  application:
    host: localhost
    port: 5672
    ...

If you just want to get started without configuring anything, Qusion.start() will use the default options if it can’t find a config file. And, finally, you can give options directly to Qusion.start() like this:

  Qusion.start(:host => "my-amqp-broker.mydomain.com", :user => "me", :pass => "am_I_really_putting_this_in_VCS?")

Bugs? Hacking?

If you find any bugs, or feel the need to add a feature, fork away. You can also contact me directly via the email address in my profile if you have any quesions.

Shouts

  • Qusion’s code for Phusion Passenger’s starting_worker_process event was originally posted by Aman Gupta (tmm1) on the AMQP list
  • Brightbox’s Warren library provides some similar functionality. It doesn’t support webserver-specific EventMachine setup, but it does have built-in encryption and support for the synchronous (non-EventMachine) Bunny AMQP client.

dan@kallistec.com