vartec
vartec

Reputation: 134601

ZeroMQ selective pub/sub pattern?

I'm trying to design ZeroMQ architecture for N front-end servers and M back-end workers, where front-end servers would send task to back-end ones. Front-end servers do have information about back-end ones, but back-end ones do not know about front-end. I have two types of tasks, one type should use round robin and go to just one back-end server, while other type should be broadcasted to all back-end servers. I don't want to have a central broker, as it would be single point of failure.

For the first type of tasks request/response pattern seems to be the right one, while for the second it would be publisher/subscriber pattern. But how about pattern combining the two? Is there any patter that would allow me to select at send time if I want to sent message to all or just one random back-end servers?

The solution I've come up with is just use publisher/subscriber and prepend messages with back-end server ID and some magic value if it's addressed to all. However, this would create lot unnecessary traffic. Is there cleaner and more efficient way to do it?

Upvotes: 4

Views: 1078

Answers (2)

tchap
tchap

Reputation: 1057

What I see as the only possibility is to use the DEALER-ROUTER combination. DEALER at the frontend, ROUTER at the backend. Every frontend server shall contain a DEALER socket for every backend server (for broadcast) and one DEALER socket on top connected to all the backend servers at once for the round-robin thing. Now let me explain why.

  1. You can't really use PUB-SUB in such a critical case, because that pattern can very easily drop messages silently, it does not queue. So in fact the message posted to PUB can arrive to any subset of SUB since it's (dis)connecting in the background. For this reason you need to simulate broadcast by looping over DEALER sockets assigned to all the background servers. It will queue messages if the backend part is not connected, but beware of the HWM. The only final solution is to use heartbeat to know when a backend is dead and destroy the socket assigned to it.
  2. A ROUTER socket at the background is a logical solution since you can asynchronously accept any number of requests and since it's a ROUTER socket it is super easy to send the response back to the frontend that requested the task. By having a single ROUTER in the background servers you can make it in a way that they are not even aware of the fact that there is a broadcast happening, they see everything as a direct request to them. Broadcasting is purely a frontend thing. The only issue with this solution might be that if your backend server is not fast enough, all the frontend servers may fill it up so that it reaches the HWM and starts dropping the packages. You can prevent this by having more threads/processes processing the messages from the ROUTER socket. zmq_proxy() is a useful function for this stuff.

Hope this helps ;-)

Upvotes: 1

Richard Harrison
Richard Harrison

Reputation: 19393

I'd probably use pub sub message envelopes - if you're using pub/sub broadcast over UDP I don't believe it will generate unnecessary network traffic but it will incur extra processing however like most of these things it's a trade-off between design elegance and performance. ØMQ tends to take the route of performance first, but I'd be inclined to measure it and use quantified performance results to decide if this was acceptable.

For me the elegant solution would be to use two sets of sockets because this in itself is differentiating the workflow through the system - whereas using a single socket is mixing things up in a very non ØMQ way, these should be different to allow for future changes and dynamic/unstable systems.

Upvotes: 1

Related Questions