Saturday, March 30, 2013

An Intro to ZeroMQ(ØMQ) On Ubuntu 12.04

What is ØMQ?


ØMQ (also spelled as ZeroMQ, 0MQ, zmq) is an open source (LGPL), brokerless high-performance asynchronous messaging library. It is main aim is for scalable distributed or concurrent applications   It gives you sockets that carry atomic messages across various transports like in-process, inter-process, TCP, and multicast (N-to-N with patterns like fanout, pub-sub, task distribution, and request-reply). The library is designed to have a familiar socket-style API.  

It is easy to use. Simply reference the ØMQ library, and you can happily send messages between your applications.

It's fast (see the following post Message Queue Shootout!).  



It is available in many languages (bindings) in C++, C#, Clojure, CL, Delphi, Erlang, F#, Felix,  Go, Haskell, Haxe, Java, Lua, Node.js, Objective-C, Perl, PHP, Python, Q, Racket, Ruby, Scala, Tcl, Ada, Basic, ooc.  But written in C++.

It is brokerless i.e. ØMQ does not require any server process. In effect, your application endpoints play the server role. This makes deployment simpler, but there are no obvious place to look at when things go wrong.  A simple example of this problem is to kill the server example in the "Hello World" below while the client is running. The client will hang forever (... I only waited a few minutes...) even when the server is restarted.

It is not part of the Advanced Message Queuing Protocol (AMQP) group of Message Brokers like RabbitMQ or ActiveMQ, and in a lots of ways is a different beast from those "traditional" messaging systems.  IMO, only Kafka can be considered similar at least in terms of performance but even then the comparison is skewed as ØMQ has no guarantee of delivery (non-durable queues).


Ubuntu Installation

There is a PPA available on the web (https://launchpad.net/~chris-lea/+archive/zeromq) for 12.04 (Precise):
deb http://ppa.launchpad.net/chris-lea/zeromq/ubuntu precise main 
deb-src http://ppa.launchpad.net/chris-lea/zeromq/ubuntu precise main 

Which I did not try since I used the tar ball available on the ØMQ download page.  

To grab the release, in this case 3.2.2:

    wget http://download.zeromq.org/zeromq-3.2.2.tar.gz
    tar -zxf zeromq-3.2.2.tar.gz
    cd zeromq-3.2.2

The ØMQ build instructions informs you that the following dependencies are required libtoolautoconfautomake as well as uuid-dev, and of course build-essential.

    sudo apt-get install libtool autoconf automake uuid-dev build-essential

Build and install:

    ./configure
    make
   # To install system wide
   sudo make install
   # Run ldconfig to create teh necessary links
   sudo ldconfig

To see all configuration options, run ./configure --help. Read INSTALL for more details.

A "Hello World" example

This is well documented on the ØMQ guide. Using the C example, first, the client.c file (from the ØMQ guide):

// Hello World client
#include <zmq.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
int main (void)
{
printf ("Connecting to hello world server…\n");
void *context = zmq_ctx_new ();
void *requester = zmq_socket (context, ZMQ_REQ);
zmq_connect (requester, "tcp://localhost:5555");
int request_nbr;
for (request_nbr = 0; request_nbr != 10; request_nbr++) {
char buffer [10];
printf ("Sending Hello %d…\n", request_nbr);
zmq_send (requester, "Hello"50);
zmq_recv (requester, buffer, 100);
printf ("Received World %d\n", request_nbr);
}
zmq_close (requester);
zmq_ctx_destroy (context);
return 0;
}

A slightly modified server.c file that indicates the ØMQ version at startup:

// Hello World server
#include <zmq.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
int main (void)
{
    int major, minor, patch;
zmq_version (&major, &minor, &patch);
printf ("Current 0MQ version is %d.%d.%d\n", major, minor, patch);

// Socket to talk to clients
void *context = zmq_ctx_new ();
void *responder = zmq_socket (context, ZMQ_REP);
int rc = zmq_bind (responder, "tcp://*:5555");
assert (rc == 0);

    printf("0MQ server start at %d.", 5555);
while (1) {
char buffer [10];
zmq_recv (responder, buffer, 100);
printf ("Received Hello\n");
zmq_send (responder, "World"50);
sleep (1); // Do some 'work'
}
return 0;
} 

The only thing to remember when compiling is to specify the linked library (g++/gcc linking refresher) when compiling:
  
    g++ -0 client client.c -lzmq
    g++ -0 server server.c -lzmq

Start the server, then the client:

    ./server
    ./client

The client will send 10 "Hello"s to the server that will reply with "World".

That is it.

More info: http://www.zeromq.org/. Now, read the guide

Some interesting links: 

No comments:

Post a Comment