RabbitMQ is a messaging broker, and is an excellent choice to maintain task Queues. Here is how you can configure RabbitMQ on AWS in an autoscaling load balanced environment.

Installing RabbitMQ On Ubuntu/Debian

# Add the official rabbitmq source to your apt-get sources.list sudo sh -c "echo 'deb http://www.rabbitmq.com/debian/ testing main' > /etc/apt/sources.list.d/rabbitmq.list"; # Install the certificate wget http://www.rabbitmq.com/rabbitmq-signing-key-public.asc sudo apt-key add rabbitmq-signing-key-public.asc rm rabbitmq-signing-key-public.asc # Now install the latest rabbitmq sudo apt-get update sudo apt-get install rabbitmq-server

The above script will download the latest version of the RabbitMQ site and install it. Here are the references for the Installation instructions.

Installing RabbitMQ on RPM-based Linux :

rpm –import https://www.rabbitmq.com/rabbitmq-signing-key-public.asc yum install rabbitmq-server-3.5.4-1.noarch.rpm

Install RabbitMQ-Management Plugin:

RabbitMQ management plugin is a Web UI for administration purposes. You can use it to view the queues, queue elements and a number of consumers. The management plugin is included in the RabbitMQ distribution. To enable it, use the below command.

sudo rabbitmq-plugins enable rabbitmq_management

Create an AMI of this EC2 Instance:

Once you have installed RabbitMQ and configured it, create an AMI out of it. Note the AMI ID. So that, you can use it later in the scripts to automatically scale out or scale in RabbitMQ.

Configuring RabbitMQ Cluster on AWS:

Now that we have our AMI, we will create a cluster on AWS. A cluster provides fault tolerance and load balancing.

Step 1: Create Security Groups RabbitMQ requires several ports to work. Some ports are needed for inter-node communication, others are needed between clients and RabbitMQ, and a third bucket is the HTTP based management interface.

RabbitMQ uses the following ports:

4369 for epmd 5672 and 5671 25672 15672

If you are deploying this within a VPC (which you should) – then these ports will be open to traffic from other nodes in the VPC. If you are deploying this on an EC2 classic, you will have to create a Security group that allows instances to communicate over these ports.

Step 2: Create a Load Balancer

Create a new classic load balancer Set the protocol to TCP Forward port 5672 and 15672 to the instances over TCP/IP Assign security group that you created in the first step. In Health Check, ping port 5672 Don’t add any instances yet, because we haven’t launched any

Step 3: Create a Launch Configuration

Choose the AMI that we created earlier Expand Advanced Details, Copy paste the python script in “UserData” from the section below Note: Replace the _url value with the DNS Name of the load balancer that was created in Step 1. To get the DNS name, go to load balancer page. Then select the load balancer that is created. Below this you can see the DNS name. Click next until you reach the security group window. Then, select an existing security group and select the security group that is created in step 1.

Step 4: Create an auto-scaling Group

Check “Create an Auto Scaling group from an existing launch configuration”. Choose the launch configuration that was created from the previous step. Expand Advanced Details, In Load Balancing, check to Receive traffic from Elastic Load Balancer(s). Then choose the Load balancer created in step 2. In the scaling policies, RabbitMQ machines should be scaled based on Memory Utilization. Remove 1 instances when memory utilization <= 30 for 300 seconds. Add 1 instances when memory utilization >= 70 for 60 seconds. With this configuration, you should see two instances come up in the instances page.

RabbitMQ Launch Configuration Script

This configuration, with go into the Launch Configuration as “User Data”.

Note: The variable ‘_url’ should be updated with the load balancer URL.

#!/usr/bin/env python import json import urllib2,base64 if __name__ == "__main__": prefix = '' from subprocess import call call(["rm", "-rf", "/var/tmp/aws-mon"]) call(["rabbitmqctl", "add_vhost", "/admin"]) call(["rabbitmqctl", "add_user", "admin", "admin"]) call(["rabbitmqctl", "set_user_tags", "admin", "administrator"]) call(["rabbitmqctl", "set_permissions", "-p", "/admin", "admin", ".*", ".*", ".*"]) call(["rabbitmqctl", "set_policy", "-p", "/admin", "server-qa-cluster", ".*?", ' {"ha-mode":"all","ha-sync-mode":"automatic"}']) call(["rabbitmqctl", "stop_app"]) try: _url = 'http://ELB-rabbitmq-QA.us-east-1.elb.amazonaws.com:15672/api/nodes' print prefix + 'Get json info from ..' + _url request = urllib2.Request(_url) base64string = base64.encodestring('%s:%s' % ('admin', 'admin')).replace('

', '') request.add_header("Authorization", "Basic %s" % base64string) data = json.load(urllib2.urlopen(request)) print prefix + 'request ok… finding for running node' for r in data: if r.get('running'): print prefix + 'found running node to bind..' print prefix + 'node name: '+ r.get('name') +'- running:' + str(r.get('running')) from subprocess import call call(["rabbitmqctl", "join_cluster",r.get('name')]) break; pass except Exception, e: print prefix + 'error during add node' finally: from subprocess import call call(["rabbitmqctl", "start_app"])

The above code will dynamically add the upcoming instances to the cluster based on the ELB provided in the code as the URL.

What do the call methods mean?

By default, RabbitMQ stays in the reset state. We need to create users and set up the permission for the user as the administrator for future logins. The commands to set up are as follows.

The below code block creates User “Admin” with Password “Admin” – change it at your ease.

call(["rabbitmqctl", "add_vhost", "/admin"]) call(["rabbitmqctl", "add_user", "admin", "admin"]) call(["rabbitmqctl", "set_user_tags", "admin", "administrator"]) call(["rabbitmqctl", "set_permissions", "-p", "/admin", "admin", ".*", ".*", ".*"])

Once the slaves’ nodes are set up, we need to add a policy to replicate/synchronize the elements of the slave nodes. It can be done using the command in the parent node. Also, it will be applicable across all other nodes in the cluster.

call(["rabbitmqctl", "set_policy", "-p", "/admin", "server-qa-cluster", ".*?", '{"ha-mode":"all","ha-sync-mode":"automatic"}'])

You will have to stop the service and fire a command requesting it to join one of the already running rabbitMQ services on other machines. The cluster between both the machines is automatically created when the ‘join_cluster’ request is fired.

# Stop the RabbitMQ application. As it is running as a stand-alone queue service sudo rabbitmqctl stop_app # Start RabbitMQ by requesting to create the cluster with the 2-machine sudo rabbitmqctl join_cluster rabbit@<machine-2-ip> –ram # Start the RabbitMQ application. As it is running as a stand-alone queue service sudo rabbitmqctl start_app