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 libtool, autoconf, automake 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>
#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");
{
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", 5, 0);
zmq_recv (requester, buffer, 10, 0);
printf ("Received World %d\n", request_nbr);
}
zmq_close (requester);
zmq_ctx_destroy (context);
return 0;
}
for (request_nbr = 0; request_nbr != 10; request_nbr++) {
char buffer [10];
printf ("Sending Hello %d…\n", request_nbr);
zmq_send (requester, "Hello", 5, 0);
zmq_recv (requester, buffer, 10, 0);
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>
#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);
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, 10, 0);
printf ("Received Hello\n");
zmq_send (responder, "World", 5, 0);
sleep (1); // Do some 'work'
}
return 0;
char buffer [10];
zmq_recv (responder, buffer, 10, 0);
printf ("Received Hello\n");
zmq_send (responder, "World", 5, 0);
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.
Some interesting links:
- Interesting comparison on stackoverflow: http://stackoverflow.com/questions/731233/activemq-or-rabbitmq-or-zeromq-or
- Message Queue Shootout!
- "Kafka: a Distributed Messaging System for Log Processing" http://www.systemswemake.com/papers/kafka, the paper http://research.microsoft.com/en-us/um/people/srikanth/netdb11/netdb11papers/netdb11-final12.pdf
No comments:
Post a Comment