What is ZeroMQ?
At its core, ZeroMQ (aka zmq
) is a library of messaging components useful for transferring information between two or more applications. These can be anything, from two processes on the same machine to hundreds of servers communicating over the internet. ZeroMQ is built on top of traditional networking technologies like TCP sockets and automatically handles their limitations like splitting large messages into multiple TCP packets for transfer, but adding them back together before the other side processes them as a single message again. It also optionally allows authentication and encryption, although the verification of credentials needs to be implemented by the developer as well.
It aims to be minimal and only handles networking, without making any assumptions of the business logic implemented on top of it. This makes it powerful and flexible at the same time, giving all the freedom of choice to the developers who use it.
PAIR (bidirectional one-to-one)
The simplest form of networking offered by zeromq is the PAIR
socket type, allowing communication in both directions between exactly two sockets. This is almost identical to plain TCP networking, but with some added benefits like automatic message chunking/merging for larger messages and support for encryption and authentication. Using PAIR
sockets is typically used for tightly coupled pairs, like communicating processes or threads, but networked usage is also possible.
PUB/SUB (one-to-many broadcasting)
The publish / subscriber pattern is available in zeromq through the PUB
(publisher) and SUB
(subscriber) socket types. A PUB socket acts as a server, that one or more SUB sockets can connect to. The publisher can send messages to "topics" (any arbitrary string, think of it as custom categories), and subscribers can decide what "topics" they want to receive messages for. Subscribers receive all messages published in their subscribed topics, but only if they are connected in time - messages sent before connecting are not stored or repeated for them.
Pub/sub is a great pattern for situations where you need data from one point to be broadcast to many others, for example to broadcast notifications like weather warnings to many mobile devices of people living in the danger zone.
PUSH/PULL (one-to-many or many-to-one load-balancing)
The need to balance work across multiple workers is common to many networked applications, and zeromq offers a builtin solution in the form of PUSH
and PULL
sockets. The PUSH
socket distributes messages evenly across all connected PULL sockets, in a round-robin fashion. A PULL
socket simply receives messages and processes them. These two sockets can be combined in two ways: fan-out and fan-in.
Fan-out means a single PUSH
socket acts as a load balancer to evenly process a set of tasks across multiple connected PULL
sockets (one-to-many). Fan-in is the inverse of this, where many PUSH
sockets all send messages to a single PULL
socket (many-to-one), useful for collecting the results of previously load-balanced jobs or tasks like sending logs from many devices to a central logging server.
REQ/REP (synchronous many-to-one)
Patterns similar to that of web servers is possible through REQ
and REP
sockets. In this scenario, a REQ
socket is a client making a request to a REP
socket, blocking until it receives a response. This can be repeated any number of times, mirroring the common client/server model in use by many networking services today.
A REP
socket can be used by multiple REQ
sockets, but will only process one at a time (synchronous), blocking all the others in the meantime. For services with little computational overhead per request or low traffic this is fine, but starts to become problematic with growing connection counts or increased latency, for example if a single response takes some time to complete.
ROUTER/DEALER (many-to-many custom communication)
For anything not covered by the previously discussed message transfer patterns, zeromq provides a last resort, namely the ROUTER
and DEALER
sockets. These sockets are intentionally less opinionated about the direction and circumstances of communications. They work by first defining a ROUTER
socket, which acts as a central proxy for messages from or to DEALER
sockets. The difference to all other forms of sockets is, zeromq doesn not bring business logic to dictate how.
Want to use a ROUTER
as a load balancer from many publishers to many workers? Or only send data from the DEALERS
to the ROUTER
? Perhaps even set a unique ID for each DEALER
and add that to every message, so the ROUTER
can proxy messages between DEALER
sockets directly? These socket can do it all.
The ROUTER
and DEALER
sockets are highly customizable and enable developers with more specific needs to build their own communication platform on top of the quality of life tooling of zeromq. You could even build your own message queuing server if you want to!