Zeromq message template for many, many requests / responses

I am very new to ZeroMQ. I have read the manual and am currently looking at examples as well as browsing other relevant information on the Internet. I have hesitation about which message templates to use or if I should use a combination of two templates.

I have an existing software application that has a messaging system for home users that needs to be replaced. I have a pretty simple architecture:

|Client|<----->|driver1| | |---|driverN| 

Currently, only one β€œclient” is connected to the driver, and there can be many drivers.

(in fact, the client, in this case, is not really my client application, but rather an intermediary. For this discussion, it can be considered as a client)

Messages:

  • The client issues commands to the driver.
  • Drivers return status / status information in response to commands.
  • Drivers create data elements (i.e. do not contain status / status information)
  • Some client messages go to all connected devices, some of them are directed to only one driver.

Drivers can exist on the same system or remotely on a local network. This is not a public network.

Currently, I think that I will have a pub and auxiliary socket for each driver and a sub / pub socket on the client. Messages should not be deleted after connection. I assume that the client will subscribe to different types of driver data, and then the driver will subscribe to messages from client commands.

Important considerations: low latency, minimum possible bandwidth.

I would be grateful for any suggestions or recommendations! Thanks in advance!

+4
source share
1 answer

You have chosen a great exercise, that's for sure!

Read them, they provide a basic request / response implementation using a custom proxy router-router with polling and should address your client-device problem.

The solution is synchronous, so any request sent from client blocks until it receives a response. Personally, I would like to use async for request and response for complete flexibility, but this solution is more complex. However, the book refers to Freelance and Dealer/Router examples illustrating an asynchronous request / response.

Here is an example of a many-to-many synchronous request / response. You MUST know how ZeroMq wrapping works in order to fully understand the mechanics of this approach; see example lbbroker1 .

Client

Set the client ID using setIdentity() ; important for routing the response.
The client sends requests for device1 , device2 , etc. In the loop; if the device exists, status messages returned from the specific device; otherwise, β€œno device” is returned to the client.

  Socket client = context.socket(ZMQ.REQ); client.setIdentity("client1".getBytes()); client.connect("tcp://localhost:5550"); for( int i = 0; i < 5; i++){ client.send("device" + i); String reply = client.recvStr(); log("Received message: " + reply); Thread.currentThread().sleep(1000); } 

Device

The device sets the id in the same way as the client for unique routing.
The device sends device.send("DEVICEREADY") to the server to signal online availability.
The device executes recvStr() three times to read the full envelope from the server.

 String deviceId = "device1" Socket device = context.socket(ZMQ.REQ); device.setIdentity(deviceId.getBytes()); device.connect( "tcp://localhost:5560"); device.send( "DEVICEREADY"); while (!Thread.currentThread().isInterrupted()) { String clientAddress = device.recvStr(); String empty = device.recvStr(); String clientRequest = device.recvStr(); //create envelope to send reply to same client who made request device.sendMore(clientAddress); device.sendMore(""); device.send( "stauts on " + deviceId + " is ok"); } 

Server (Router / Router)

User proxy using ROUTER sockets; clients connect to an external ROUTER connector, and devices connect to a server router. Polling servers on both message sockets.

 Context context = ZMQ.context(1); Socket frontend = context.socket(ZMQ.ROUTER); Socket backend = context.socket(ZMQ.ROUTER); frontend.bind( "tcp://localhost:5550"); backend.bind( "tcp://localhost:5560"); Poller poller = new Poller(2); poller.register(frontend, Poller.POLLIN); poller.register(backend, Poller.POLLIN); while (!Thread.currentThread().isInterrupted()) { poller.poll(); //frontend poller if (poller.pollin(0)) { String clientId = frontend.recvStr(); String empty = frontend.recvStr(); //empty frame String deviceId = frontend.recvStr(); //if client is requesting to talk to nonexistent deviceId, //return message "no device", otherwise, create envelope and send //request on backend router to device. if( deviceMap.get( deviceId) == null ){ frontend.sendMore(clientId); frontend.sendMore(""); frontend.send("no deviceId: " + deviceId); } else { //request envelope addressed to specific device backend.sendMore(deviceId); backend.sendMore(""); backend.sendMore(clientId); backend.sendMore(""); backend.send("hello from " + clientId); } } //backend poller if(poller.pollin(1)){ String deviceId = backend.recvStr(); String empty = backend.recvStr(); String clientId = backend.recvStr(); //device signaling it ready //store deviceId in map, don't send a response if( clientId.equals("DEVICEREADY")) deviceMap.put(deviceId, deviceId); else { //the device is sending a response to a client //create envelope addressed to client, send on frontend socket empty = backend.recvStr(); String reply = backend.recvStr(); frontend.sendMore(clientId); frontend.sendMore(""); frontend.send(reply); } } } 
+7
source

Source: https://habr.com/ru/post/1494381/


All Articles