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
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++));
}
}