Reputation: 67
For reasons of my work, using ZeroMQ REQ/REP
pattern, I decided to make the replier work of the server in a different thread from the principal. The code that I'm going to show summarize that approach:
import time
import zmq
import threading
def make_work(context):
socket = context.socket(zmq.REP)
socket.bind("tcp://*:5555")
message = socket.recv()
print("Received request: %s" % message)
#Do some 'work'
time.sleep(1)
#Send reply back to client
socket.send(b"World")
socket.close()
context = zmq.Context()
thr = None
while True:
if not thr or not thr.is_alive():
thr = threading.Thread(target = make_work, args = (context, ) )
thr.start()
I modified the hello world example of the pyzmq guide. So, my problem is that when I run the hello world client from the doc made by Pieter Hintjens, the expected behavior is : for each thread that I'm creating, the replier socket that I open, sends the answer to the client, but the real behavior is, that after the first thread, both sides of the connection blocks. If I make a poll in the client side, and retry to send, it's success, but this is not that I want. It is possible a successful receive in the server side, in the new thread?
Upvotes: 2
Views: 181
Reputation: 1
Q : It is possible a successful receive in the server side, in the new thread?
Yes, it is.
Your half of the code ( client still invisible ) suffers from very low efficiency. It takes some time to create + setup + self-establish a distributed-computing infrastructure ( re-instantiate a Socket
-instance, configure its local side, ask O/S to provide a port for .bind()
, wait for others to successfully detect a presence of a new counterparty to .connect()
and actually do a .connect()
to setup and negotiate a ling there and back ...), all that done for but a one message and .close()
?
Well, if one wishes.
Smart systems re-use resources without paying twice, the less many times, for what has already been paid for.
Plus, your infinite-loop "re-instated" thread takes additional side-effects you do not see from the code. Besides all the above sketched systematic ( yet each call re-repeated ) delays, there is one more, potentially forever blocking delay - the zmq.LINGER
- a secret blocker.
Early versions of the ZeroMQ API worked with a default of zmq.LINGER == -1
- being able to block inifitely long on the .close()
method. More recent versions, the v4.3-stable for sure, use a zmq.LINGER
default of 1000 [ms]
.
Anyway, a professional distributed-computing design explicitly controls the instance parameters and sets the .setsockopt( zmq.LINGER, 0 )
for safety purposes always and without exception.
If interested, feel free to read more details about other silent dangers of the REQ/REP
mutual deadlocks in many other ZeroMQ posts
Upvotes: 1