• Stars
    star
    111
  • Rank 314,510 (Top 7 %)
  • Language
    Ruby
  • License
    MIT License
  • Created over 15 years ago
  • Updated almost 15 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Using AMQP as a Queuing Backend for Web Apps Should Be Easy

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.

Before You Start¶ ↑

Qusion makes it easy to just install the plugin and start using AMQP in your application. But there are many ways to use background jobs within a Rails app, so it’s worth taking some time to consider the tradeoffs of each approach.

  • If your background job needs are simple and you’re using a relational database, Delayed::Job lets you schedule background tasks through the database. You won’t need to run another application (the AMQP Broker) to keep your app running.

  • The 0.6.x version of the ruby amqp library may drop messages when the AMQP broker goes down. Pivotal Labs has discussed this problem on their blog. This issue will likely be addressed in the 0.7.0 release of amqp, but can be avoided entirely using a synchronous amqp library such as bunny. For a ready-made background job solution using Bunny to publish jobs to the queue, see Minion.

  • Qusion runs EventMachine in a separate thread on Phusion Passenger, Mongrel, and other non-evented servers. There are some inefficiencies in Ruby 1.8’s threading model that make running EM in a thread quite slow. Joe Damato and Aman Gupta have created a patch for the problem which is included in an experimental branch of REE. You can learn more about the patch from Phusion’s Blog.

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.

[email protected]

More Repositories

1

Decider

Flexible and Extensible Machine Learning in Ruby
Ruby
383
star
2

deep_merge

Recursive Merging for Ruby Hashes
Ruby
160
star
3

critical

Infrastructure Monitoring As Code
Ruby
68
star
4

moqueue

Mocktacular Companion to AMQP Library. Happy TATFTing!
Ruby
67
star
5

knife-plugins

my .chef/plugins/knife/
Ruby
27
star
6

nom_nom_nom

A Simple Status Server for Chef
JavaScript
22
star
7

cookbooks

Opscode Cookbooks for Chef
Ruby
12
star
8

partials

Demo of Template Partials in Chef 11
Ruby
12
star
9

knife-boxer

Frictionless Chef Environments via Checksum-Versioned Cookbooks
Ruby
10
star
10

omnibus-rubies

Matrix of Ruby/Rubygems Versions in Omnibus Form
Ruby
8
star
11

chef-workflow2-prototype

demoware
Ruby
7
star
12

teeth

Fast parsing of log files in Ruby
C
6
star
13

policyfile-jenkins-demo

demo app for policyfiles
Ruby
4
star
14

gem-mirror-tools

Scripts and Hacks to make Gem Mirroring Work
Ruby
2
star
15

acts_as_bourbon

GitHub Recommendation Contest
2
star
16

chef-data-bindings

Data Binding DSL for Chef: Make cookbooks more readable, portable, and maintainable
Ruby
2
star
17

kallistec-thor-tasks

My Own System Thor Tasks
2
star
18

resource-tracking-demo

work in progress
Ruby
1
star
19

QusionTestHarness

A Basic Rails App That I Use to Test Qusion
Ruby
1
star
20

seth

sethsethsethsethseth
Ruby
1
star
21

exampleproject

A bunch of slow running specs including one that randomly passes and fails. For demonstrating distributed CI.
Ruby
1
star
22

rubygems-json-list

JSON output for gem list
Ruby
1
star
23

docsite

Automated RDoc Site Generator
Ruby
1
star
24

queue-patch

Helps me stay on top of pull requests for opscode/chef
Ruby
1
star
25

omnibus-rubygems-mirror

Omnibus Builds for a Gem Mirror Server using gem-mirror-tools
Ruby
1
star
26

panopticon

Get performance statistics on remote servers using the magic of Nanite
Ruby
1
star