Quick ZeroMQ Round Robin (push-pull) with Python

Posted on Friday, August 10, 2012



Before I get too far into this one I finally found the documentation for PyZMQ API at http://zeromq.github.com/pyzmq/api/index.html [1].

This has been very helpful to me in figuring some of this stuff out.

… Now onto the problem at hand, how do you do round-robin with ZeroMQ?  For those unfamiliar with the concept of round robin you can see the Wikipedia page about it here http://en.wikipedia.org/wiki/Round-robin_scheduling [2].  In short you can have a group of workers and a foreman handing out work.   Think of your machines as the workers, let’s say there are 10.  The foreman gets a job and hands it out to the first worker, the second job to the second, and so on until he gets the last worker (the 10th).   After he has run out of workers to hand jobs to he starts the process over again handing the next job to the first worker…


Now beyond this simple example you can expand the idea out.  What if a worker leaves?  What if he comes back?  What if you have a job and the next worker is too busy to grab it?   ZeroMQ handles a lot of these ideas right out of the box.




In ZeroMQ they use the term  PUSH/PULL which is round-robin if you go to this page http://api.zeromq.org/2-1:zmq-socket [3] and search for ZMQ_PUSH and ZMQ_PULL you will get a lot more details then I will show here.  To quote the page

The pipeline pattern is used for distributing data to nodes arranged in a pipeline. Data always flows down the pipeline, and each stage of the pipeline is connected to at least one node. When a pipeline stage is connected to multiple nodes data is round-robined among all connected nodes.

A socket of type ZMQ_PUSH is used by a pipeline node to send messages to downstream pipeline nodes.




This guide assumes you already have ZeroMQ and related libraries installed and running on your machine.  If you have not installed any ZeroMQ refer to this guide Quick ZeroMQ with Python 
   This code was all written and tested on an Ubuntu 12.04 server installation.



Push


First let’s write the push program

I am going to run this on a local virtual Ubuntu machine that already has all the necessary zeroMQ libraries installed.  The machines address is 192.168.0.161

Open the document for editing


       > vi zeroMQ_PUSH.py





#!/usr/bin/python
 
import zmq
import time
 
 
ctx = zmq.Context()
push_socket= ctx.socket(zmq.PUSH)
 
push_socket.bind('tcp://*:1234')
 
 
for x in range(20):
    msg = str(x) + " , " + str(time.time())
    print x
    push_socket.send(msg)
    #Pause 1 second
    time.sleep(1)



This is a simple program it binds a push to the port 1234.
It starts sending out messages via push (round robin)



Pull



I am going to run this on a local virtual Ubuntu machine that already has all the necessary zeroMQ libraries installed.  The machines address is 192.168.0.162 and 192.168.0.163

Open the document for editing


       >    vi zeroMQ_PULL.py




#!/usr/bin/python
 
import zmq
 
ctx = zmq.Context()
pull_socket = ctx.socket(zmq.PULL)
 
pull_socket.connect('tcp://192.168.0.161:1234')
 
 
while True:
    msg = pull_socket.recv()
    print msg


Now run this program from 2 machines 192.168.0.162 and 163





They both sit there and wait for messages to come in.

Now, once they are both running, start up the PUSH program

Then you will see the work getting divided out between the two.  On the first machine













You can see it gets the first two messages in a row (probably because the second machine has not yet connected up with the PUSH machine)










Here is the output from the second machine.


If I run this again and kill one of the PULL machines midway through….



You can see the second machine now gets all the messages, since the first machine was turned off after message 7.











If I turn it off then bring it back…














You can after message 7 the second machine came online and the work was distributed between the two.



ZeroMQ does a lot of the heavy lifting, getting back connections so you do not have to.  You can focus on programming new features rather than doing all this heavy lifting maintaining connections, dropouts and reconnections.




References
 [1]  The PyZQM API
       Visited 08/2012
[2]  Wikipedia: Round-robin scheduling
       Visited 08/2012
[3]  zmq socket
       Visited 08/2012




No comments:

Post a Comment