Introduction and use of ZeroMQ

Keywords: socket Java network encoding

What I wrote last time Introduction and use of ZeroMQ (1)

Pipeline pattern

PipeLine mode is used for task allocation, usually in multi-level PipeLine, one or several nodes push the work to many workers, and then push the results to one or several collectors in turn. This pattern is reliable in most cases, because it does not drop messages unless the node is unexpectedly disconnected. It is scalable because nodes can join at any time.

ZeroMQ supports PipeLine through two types:

  • PUSH type
  • PULL type

PUSH socket

PUSH uses a circular algorithm to send messages as a group of anonymous PULL peers. The receive operation does not have this Socket type implementation.

When PUSHSocket enters into mute state because it has reached the high water level of all downstream nodes, or if there is no downstream node at all, any sending operation on the Socket will be blocked until the mute state ends or at least one downstream node can be sent; the message will not be discarded.

Feature summary:

   
Compatible peer socket PULL
direction one-way
Send / receive mode Send only
Access routing strategy Not applicable
Outgoing routing policy Round robin
Action in mute state block

PULL socket

The PULL type talks to a group of anonymous PUSH peers and receives messages using a fair queuing algorithm.

This socket type is not implemented for this send operation.

Feature summary:

   
Compatible peer socket PUSH
direction one-way
Send / receive mode Receive only
Access routing strategy Fair queuing
Outgoing routing policy Not applicable
Action in mute state block

Code instance

PUSH:

package ndm2.ndm2;

import java.io.IOException;
import java.util.Random;

import org.zeromq.SocketType;
import org.zeromq.ZContext;
import org.zeromq.ZMQ;
import org.zeromq.ZMQ.Socket;

public class ZMQDemoPush {
	
	public static void main(String[] args) throws InterruptedException, IOException {
		ZContext context = new ZContext();
		ZMQ.Socket sender = context.createSocket(SocketType.PUSH);
		sender.bind("tcp://localhost:5557");
        for (int i = 0; i < 100; ++i) {
        	sender.send("this is a test", 0);
        	Thread.sleep(1000); //  Give 0MQ time to deliver
        }	
	}

}

pull:

package ndm2.ndm2;

import java.io.IOException;
import java.util.Random;

import org.zeromq.SocketType;
import org.zeromq.ZContext;
import org.zeromq.ZMQ;
import org.zeromq.ZMQ.Socket;

public class ZMQDemoPull {
	
	public static void main(String[] args) throws InterruptedException, IOException {
		ZContext context = new ZContext();
		ZMQ.Socket receiver = context.createSocket(SocketType.PULL);
	    receiver.connect("tcp://localhost:5557");
	    while (!Thread.currentThread().isInterrupted()) {
	    	String string = new String(receiver.recv(0), ZMQ.CHARSET).trim();
	        System.out.println(string + '.');
	    }
				
	}

}

test result

 

Exclusive pair mode

PAIR

PAIR can only connect to a single peer at a time. Messages sent through PAIR Socket are not routed or filtered.

When PAIR is muted because it has reached the high watermark of the connected peer, or if no peer is connected, any send operation on the Socket will block until the peer is available for sending; the message will not be discarded.

Although PAIR can be used for transport other than inproc, they cannot automatically reconnect and the fact that new incoming connections will be terminated, and any previous connections (including those in the closed state) will not be suitable for TCP in most cases.

Code example

  private static class Step1 extends Thread {
	        private ZContext context;

	        private Step1(ZContext context) {
	            this.context = context;
	        }

	        @Override
	        public void run() {
	            Socket xmitter = context.createSocket(SocketType.PAIR);
	            xmitter.connect("inproc://step2");
	            System.out.println("Step 1 Be ready, transmit step 2");
	            xmitter.send("I'm number one", 0);
	            xmitter.close();
	        }

	    }

	    private static class Step2 extends Thread{
	        private ZContext context;

	        private Step2(ZContext context){
	            this.context = context;
	        }

	        @Override
	        public void run() {
	            Socket receiver = context.createSocket(SocketType.PAIR);
	            receiver.bind("inproc://step2");
	           
	            String str = new String(receiver.recv(0));
	            System.out.println(str);
	            receiver.close();
	            Socket xmitter = context.createSocket(SocketType.PAIR);
	            xmitter.connect("inproc://step3");
	            System.out.println("Step 2 Be ready, transmit step 3");
	            xmitter.send("I'm number two", 0);
	            xmitter.close();
	        }

	    }

	    private static class Step3 extends Thread {
	        private ZContext context;

	        private Step3(ZContext context) {
	            this.context = context;
	        }

	        @Override
	        public void run() {
	            Socket receiver = context.createSocket(SocketType.PAIR);
	            receiver.bind("inproc://step3");
	            String str = new String(receiver.recv(0));
	            System.out.println(str);
	            receiver.close();
	            System.out.println("Step 3 Be ready");
	        }

	    }

	    public static void main(String[] args) throws InterruptedException{
	    	ZContext context = new ZContext();
		    Thread step1 = new Step1(context);
		    step1.start();
            Thread step2 = new Step2(context);
            step2.start();
            Thread step3 = new Step3(context);
            step3.start();
            
            step1.join();
            step2.join();
            step3.join();
            System.out.println("Success!");
	    }

 

Since the following modes are not implemented, there is no instance. The following is the general content:

Client server mode

Note: this mode is still in draft state, so the zeromq library used may not support this mode!

The CLIENT SERVER mode is used to allow a single SERVER server to talk to one or more CLIENT clients. The CLIENT always starts a conversation, after which any peer can send a message asynchronously to the other party.

Client

The CLIENT type talks to one or more SERVER peers. If it is connected to multiple peers, it circulates messages sent between them. When reading, it will read fairly from each of its peers in turn. It is reliable because it does not normally discard messages.

If the CLIENT socket has established a connection, the send operation will accept the message, queue the message, and send the message as soon as the network allows. The output buffer limit is defined by the socket's high watermark. If the outgoing buffer is full or there are no connected peers, the send operation is blocked by default. The CLIENT socket does not drop messages.

Feature summary:

   
Compatible peer socket The server
direction Bidirectional
Send / receive mode Unlimited
Outgoing routing policy Round robin
Access routing strategy Fair queuing
Action in mute state block

SERVER

The SERVER type talks to zero or more CLIENT peers. Each outgoing message is sent to a specific peer CLIENT. The SERVER socket can only reply to incoming messages: the CLIENT peer must always start a conversation.

Each received message has a routing "ID, which is a 32-bit unsigned integer. To send a message to a given CLIENT peer, the application must set the routing ID of the peer on the message.

If you do not specify the routing_id, or if you do not reference a connected client peer, the send call fails. If the client peer's outgoing buffer is full, the send call is blocked. In no case will the SERVER socket discard messages.

Feature summary:

   
Compatible peer socket Customer
direction Bidirectional
Send / receive mode Unlimited
Outgoing routing policy See text
Access routing strategy Fair queuing
Action in mute state fail

 

Radio dish mode

Note: this mode is still in draft state, so the zeromq library you are using may not support this mode!

 

Radio mode is used to fan out data from a single publisher to multiple subscribers.

Radio dish is using a group (relative to the pub sub topic). Dish socket can join a group, and each message sent by radio socket belongs to a group.

A group is a null terminated string limited to 16 characters, including null. The goal is to increase the length to 40 characters, including null. The encoding of the group should be UTF8.

Use exact match (prefix match of vs PubSub) to match groups

Radio

Publishers use RADIO to distribute data. Each message belongs to a group. The message will be distributed to all members of the group. The receive operation is not implemented by this socket type.

When RADIO enters the mute state because it has reached the highest water level of the subscriber, any message that will be sent to the subscriber in question will be discarded until the mute state ends. The send operation will not block this socket type.

Feature summary:

   
Compatible peer socket dish
direction one-way
Send / receive mode Send only
Access routing strategy Not applicable
Outgoing routing policy Fan out
Action in mute state decline

DISH 

Subscribers use DISH to subscribe to RADIO distributed groups. Initially, the DISH socket did not subscribe to any groups. The send operation is not implemented by this socket type.

Feature summary:

   
Compatible peer socket radio
direction one-way
Send / receive mode Receive only
Access routing strategy Fair queuing
Outgoing routing policy Not applicable

Posted by |Adam| on Thu, 26 Mar 2020 02:15:09 -0700