Wednesday 4 November 2020

ZeroMQ Messaging Patterns

In software architecture, a messaging pattern is an architectural pattern that describes how two different parts of an application or different systems connect and communicate with each other (source: Wikipedia).

ZeroMQ supports many messaging patterns. This document lists down the most often used, with samples shown in C# CLRZMQ4 library.


1. Fire and Forget (or Push and Pull)

This is a one-way pattern, the sender sends a message to the queue and it doesn’t care about any response from the message handler. Zero MQ enforces this pattern, i.e. if the receiver sends a response, it throws an error.

It’s important not to think in terms of client/server semantics here because the component that binds to a port can either PULL or PUSH based on the socket type, and one that connects can also do either. Producer/consumer terminology suits better.

For instance, multiple senders can connect and start pushing messages on a queue (e.g. heartbeat) or say a component like a work producer that pushes work to a queue, and these get pulled by multiple workers to load balance the work (essentially multiple producers and a single consumer, or a single producer and multiple consumers).


Sender:

            var sender = new ZSocket(ZSocketType.PUSH);
            sender.Connect("tcp://127.0.0.1:5678");
            for (int i = 0; i < 5; i++)
            {
                sender.Send(new ZFrame(i));
            }        

Receiver:

            ZSocket receiver = new ZSocket(ZSocketType.PULL);
            receiver.Bind("tcp://*:5678");
            while (true)
            {
                using (ZFrame request = receiver.ReceiveFrame())
                {
                    var message = request.ReadInt32();
                    //process message
                }
            }

2. Pub-Sub

This is the multicast pattern. Subscriber registers with a queue; publisher sends the message; once queue receives the message it’s forwarded to all the subscribers. This is a data distribution pattern, involving a one-way transfer from a source to multiple consumers of data.

For example:

Publisher:

            var publisher = new ZSocket(ZSocketType.PUB);
            publisher.Bind("tcp://*:5679");

            int i = 0;
            while(true)
            {
                publisher.Send(new ZFrame(i));
                i++;
            }


Subscriber

            var subscriber = new ZSocket(ZSocketType.SUB);
            subscriber.Connect("tcp://127.0.0.1:5679");
            subscriber.SubscribeAll();
            while (true)
            {
                var msg = subscriber.ReceiveFrame();
            }


3. Request-Reply

This is a pattern to implement a service when we need to call a function remotely. Zero MQ enforces that the requestor and responder orchestrate their actions. For e.g. requestor cannot call “send” two times in a row. Once a call is made to the server, the client needs to wait for the reply.


Requestor (client)

            var requester = new ZSocket(ZSocketType.REQ);
            requester.Connect("tcp://127.0.0.1:5675");
            for (int i = 0; i < 5; i++)
            {
                //send request
                requester.Send(new ZFrame(i));
                //process server's reply
                var reply = requester.ReceiveFrame();
            }


Responder (server)

            var responder = new ZSocket(ZSocketType.REP);
            responder.Bind("tcp://*:5675");
            while (true)
            {
                using (ZFrame request = responder.ReceiveFrame())
                {
                    //wait for request
                    var message = request.ReadInt32();
                    //send response
                    responder.Send(new ZFrame(message++));
                }
            }



Shorts - week 3, 2022

Post with links to what I am reading: 1. A very good post on different aspects of system architecture: https://lethain.com/introduction-to-a...