CloudAMQP

This add-on is operated by 84codes AB

RabbitMQ as a Service

CloudAMQP

Last Updated: 19 March 2014

Table of Contents

CloudAMQP is an add-on providing RabbitMQ as a service. RabbitMQ is a high performance message broker, built in Erlang, which implements the AMQP protocol.

Messaging is the easiest and most efficient way to decouple, distribute and scale applications.

All AMQP client libraries work with CloudAMQP and there’s AMQP client libraries for almost every platform out there, including Ruby, Node.js, Java, Python, Clojure and Erlang.

Installing the add-on

CloudAMQP can be installed to a Heroku application via the CLI:

A list of all plans available can be found here.

$ heroku addons:add cloudamqp
-----> Adding cloudamqp to sharp-mountain-4005... done, v18 (free)

Once CloudAMQP has been added a CLOUDAMQP_URL setting will be available in the app configuration and will contain the canonical URL used to access the RabbitMQ cluster. This can be confirmed using the heroku config command.

$ heroku config | grep CLOUDAMQP_URL
CLOUDAMQP_URL    => amqp://user:pass@ec2.clustername.cloudamqp.com/vhost

After installing CloudAMQP the application should be configured to fully integrate with the add-on.

Local workstation setup

RabbitMQ is easy to install locally for development.

If you have… Install with…
Mac OS X brew install rabbitmq
Windows The installer
Ubuntu Linux
sudo echo "deb http://www.rabbitmq.com/debian/ testing main" >> /etc/apt/sources.list
wget http://www.rabbitmq.com/rabbitmq-signing-key-public.asc
sudo apt-key add rabbitmq-signing-key-public.asc
sudo apt-get update
sudo apt-get install rabbitmq-server
  
Other See RabbitMQ’s installation page

Use with Ruby

Ruby developers has a number of options for AMQP client libraries:

  • AMQP “the” AMQP client, evented, super fast and super well maintained
  • Bunny is the most popular synchronous client
  • Hot Bunnies is an idiomatic, fast and well-maintained (J)Ruby DSL on top of the RabbitMQ Java client

The following example will use the synchronous client Bunny and publish a message and then consume it.

require "bunny" # don't forget to put gem "bunny" in your Gemfile

b = Bunny.new ENV['CLOUDAMQP_URL']
b.start # start a communication session with the amqp server

q = b.queue("test1") # declare a queue

# declare default direct exchange which is bound to all queues
e = b.exchange("")

# publish a message to the exchange which then gets routed to the queue
e.publish("Hello, everybody!", :key => 'test1')

msg = q.pop[:payload] # get message from the queue

puts "This is the message: " + msg + "\n\n"

b.stop # close the connection

Here’s another example which uses the evented AMQP library, in combination with Sinatra and Server Sent Events. It shows how to build a simple real time application, using CloudAMQP as the backbone.

The application can also be seen live at amqp-sse.herokuapp.com.

Further reading

Use with Node.js

To access CloudAMQP (or any AMQP server) from Node.js node-amqp is the best choice.

Add amqp as a dependency in your package.json file.

"dependencies": {
  "amqp":">= 0.1.0"
}

The following code snippet show how to connect and both publish messages and how to subscribe to a queue:

var amqp = require('amqp');

function pub_and_sub() {
  var exchange = conn.exchange(''); // get the default exchange
  var queue = conn.queue('queue1', {}, function() { // create a queue
    queue.subscribe(function(msg) { // subscribe to that queue
      console.log(msg.body); // print new messages to the console
    });

    // publish a message
    exchange.publish(queue.name, {body: 'Hello CloudAMQP!'});
  });
}

var url = process.env.CLOUDAMQP_URL || "amqp://localhost"; // default to localhost
var conn = amqp.createConnection({url: url}); // create the connection
conn.on('ready', pub_and_sub); // when connected, call "pub_and_sub"

The full code example can be found at github.com/cloudamqp/nodejs-amqp-example.

Use with Clojure

Langohr is a full featured and well maintained Clojure wrapper for Java’s AMQP library.

To use it put [com.novemberain/langohr "1.0.0-SNAPSHOT"] in your project.clj file and run lein deps.

The following code snippet show how to both publish and to consume a message via CloudAMQP:

(ns clojure-amqp-example.core
  (:require [langohr.core      :as lhc]
            [langohr.basic     :as lhb]
            [langohr.queue     :as lhq]
            ))

(defn split-amqp-url [url]
  "Parses AMQP urls, eg. amqp://user:pass@lemur.cloudamqp.com/vhost"
  (if (not (nil? url))
    (let [matcher (re-matcher #"^.*://(.*?):(.*?)@(.*?)/(.*)$" url)]
      (when (.find matcher) ;; Check if it matches.
        (dissoc
          (zipmap [:match :username :password :host :vhost] (re-groups matcher))
          :match)))
    {}))

(defn -main [& args]
  (let [url (get (System/getenv) "CLOUDAMQP_URL") ;; Get the URL
        config (split-amqp-url url) ;; Split to URL to a map
        conn (lhc/connect config) ;; open the connection to CloudAMQP
        channel (.createChannel conn) ;; open a channel
        exchange "" ;; use the default excahnge
        queue (.getQueue (lhq/declare channel exchange :auto-delete true))
        payload "Hello CloudAMQP!"]
    (lhb/publish channel exchange queue payload) ;; Publish the payload
    (println (String. (.getBody (lhb/get channel queue)))) ;; Get and print
    (.close conn) ;; close the connection
    ))

The full code can be shown here: github.com/cloudamqp/clojure-amqp-example

Use with Python

The recommended library for Python to access RabbitMQ servers is Pika.

Put pika==0.9.5 in your requirement.txt file.

The following code connects to CloudAMQP, declares a queues, publish a message to it, setups a subscription and print messages coming to the queue.

import pika, os, urlparse

# Parse CLODUAMQP_URL (fallback to localhost)
url_str = os.environ.get('CLOUDAMQP_URL', 'amqp://guest:guest@localhost//')
url = urlparse.urlparse(url_str)
params = pika.ConnectionParameters(host=url.hostname, virtual_host=url.path[1:],
    credentials=pika.PlainCredentials(url.username, url.password))

connection = pika.BlockingConnection(params) # Connect to CloudAMQP
channel = connection.channel() # start a channel
channel.queue_declare(queue='hello') # Declare a queue
# send a message
channel.basic_publish(exchange='', routing_key='hello', body='Hello CloudAMQP!')
print " [x] Sent 'Hello World!'"

# create a function which is called on incoming messages
def callback(ch, method, properties, body):
  print " [x] Received %r" % (body)

# set up subscription on the queue
channel.basic_consume(callback,
    queue='hello',
    no_ack=True)

channel.start_consuming() # start consuming (blocks)

connection.close()

The full code can be seen at github.com/cloudamqp/python-amqp-example.

Celery

Celery is a great task queue library for Python, and the AMQP backend works perfectly with CloudAMQP. But remember to tweak the BROKER_POOL_LIMIT if you’re using the free plan. Set it to 1 and you should be good.

Use with Java

RabbitMQ has developed an excellent Java AMQP library.

Begin to add the AMQP library as an dependency in your pom.xml file:

<dependency>
  <groupId>com.rabbitmq</groupId>
  <artifactId>amqp-client</artifactId>
  <version>2.8.1</version>
</dependency>

Then may a simple publish and subscribe look like this:

public static void main(String[] args) throws Exception {
  String uri = System.getenv("CLOUDAMQP_URL");
  if (uri == null) uri = "amqp://guest:guest@localhost";

  ConnectionFactory factory = new ConnectionFactory();
  factory.setUri(uri);
  Connection connection = factory.newConnection();
  Channel channel = connection.createChannel();

  channel.queueDeclare("hello", false, false, false, null);
  String message = "Hello CloudAMQP!";
  channel.basicPublish("", "hello", null, message.getBytes());
  System.out.println(" [x] Sent '" + message + "'");

  QueueingConsumer consumer = new QueueingConsumer(channel);
  channel.basicConsume("hello", true, consumer);

  while (true) {
    QueueingConsumer.Delivery delivery = consumer.nextDelivery();
    String message = new String(delivery.getBody());
    System.out.println(" [x] Received '" + message + "'");
  }
}

The full code can be seen at github.com/cloudamqp/java-amqp-example.

Java AMQP resources

Dashboard

The CloudAMQP dashboard allows you to show the current message rate, which queues and exchanges you have, and the bindings between them. You can also queue and pop messages manually, among other things.

CloudAMQP Dashboard

The dashboard can be accessed via the CLI:

$ heroku addons:open cloudamqp
Opening cloudamqp for sharp-mountain-4005…

or by visiting the Heroku apps web interface and selecting the application in question. Select CloudAMQP from the Add-ons menu.

Migrating between plans

Plan migrations are easy and instant. Use the heroku addons:upgrade command to migrate to a new plan.

$ heroku addons:upgrade cloudamqp:rabbit
-----> Upgrading cloudamqp:rabbit to sharp-mountain-4005... done, v18 ($600/mo)
       Your plan has been updated to: cloudamqp:rabbit

Removing the add-on

CloudAMQP can be removed via the CLI.

This will destroy all associated data and cannot be undone!

$ heroku addons:remove cloudamqp
-----> Removing cloudamqp from sharp-mountain-4005... done, v20 (free)

Error codes

We log errors to your heroku log, below we explain the different codes.

410 - Transfer limit reached

You’ve reached your monthly transfer quota. Upgrade to a larger plan or wait until the next calendar month.

210 - Transfer in compliance

You’ve either upgraded your account (got a higher transfer limit) or it’s a new calendar month and your quota has been reseted.

420 - Connection limit reached

You’re using all your connection slots so new connections will be blocked. Either lower your connection count or upgrade to larger plan to accommodate more connections.

220 - Connections in compliance

You can now open more connections again because you’re not using all connection slots.

431 - Max channels per connection

One of your connections was closed because you’d open to many channels on it. This is often due to a bug, so check your code and make sure that you close unused channels.

432 - Max consumers per connection

One of your connections was closed because it had opened more than 12000 consumers. This is often due to a bug, so make sure that you close unused consumers.

Support

All CloudAMQP support and runtime issues should be logged with Heroku Support at support.heroku.com. Any non-support related issues or product feedback is welcome at support@cloudamqp.com or via Twitter @CloudAMQP.