Friday, September 28, 2012

Foreman and multiple ports per process

The problem

Composing an application of multiple software components is the de facto standard these days. It's rarely the case for the application to embed a database server, queue server or the like. To help manage the ever growing complexity of this kind of systems we can use Foreman - a Ruby application using a Procfile to spin off instances of declared services (same as for example Heroku uses to manage processes).

Many software components these days besides providing the core functionality tend to give the user some sort of administration interface. That interface is often available under different a port. Up until now Foreman assigned only one single port per process, via the $PORT environment variable. As I started using Foreman recently this inconvenience became a stopper for me trying to start ActiveMQ, 2 instances of MongoDB in a shard and Neo4j with my Sinatra application. All was nice but the lack of ability to start MongoDB's control interface on separate ports blew it all out of the water.

The solution

I've came to the conclusion that it'd be a really handy to use multiple ports not just for the case I just described. And so I created a ticket on GitHub for this. Being a forthcoming guy and all I decided to take a crack at implementing this functionality myself. A few hours later a working and tested solution covering all the cases was ready to be pulled in. Let's see if the maintainer will agree to pull it in :)

How to use it?

Assuming David will pull it in the formula is as follows:
alpha: command_to_start -p1 $PORT -p2 $PORT0
beta:  command_to_start -p1 $PORT1 -p3 $PORT9
What would that mean?

alpha would get assigned 2 ports: $PORT = 50xx and $PORT0 = 51xx
beta would get assigned 3 ports: $PORT = 52xx, $PORT1 = 53xx and $PORT9 = 54xx

Since Foreman makes an assumption that at most 100 ports are assigned to one variable this new functionality uses that to assign ranges for subsequent ports. And because I wanted to stay compatible with results not using this new feature the original port range numeration regardless of the usage of $PORT in the command stayed the same. That's why beta still gets the $PORT assigned even though it is not used.

Have a nice day!

Thursday, September 6, 2012

AMQP, RabbitMQ and round robin

I'm working on a set of examples of how to use RabbitMQ from different languages. Among other things I've worked on reviewing the ruby AMQP gem examples. Unfortunately when it came to demonstrating multiple consumers (a sort of scalability example) I hit a snag: even though I have had 4 consumers only the first one was used.

After setting the number of test messages to a really high number things were finally looking up - the second and third and forth consumers were involved. But that sucked big time and to prove it I started digging further to find out what actually makes it do the things it does.

:prefetch => 1 was the setting (as stated on some page) but setting it alone didn't do the trick because that made the channel get only one message and that was it. To continue receiving messages they have had to be ack'ed.

Talking is cheap - here's the example code

Have fun!