我刚刚开始使用ZMQ。我正在设计一个应用程序,其工作流程为:
我认为PUSH / PULL架构适用于此。请纠正我。
但我该如何处理这些情况?
那么如何在PUSH / PULL模型中设置类似超时的内容?
编辑:感谢user938949的建议,我收到了工作回答,我正在为后人分享。
答案 0 :(得分:71)
如果您使用的是zeromq> = 3.0,则可以设置RCVTIMEO套接字选项:
client_receiver.RCVTIMEO = 1000 # in milliseconds
但一般来说,你可以使用pollers:
poller = zmq.Poller()
poller.register(client_receiver, zmq.POLLIN) # POLLIN for recv, POLLOUT for send
poller.poll()
暂停:
evts = poller.poll(1000) # wait *up to* one second for a message to arrive.
如果没有什么可以收到, evts
将是一个空列表。
您可以使用zmq.POLLOUT
进行投票,以检查发送是否成功。
或者,为了处理可能失败的对等体的情况,a:
worker.send(msg, zmq.NOBLOCK)
可能就足够了,它总会立即返回 - 如果发送无法完成,则会引发ZMQError(zmq.EAGAIN)。
答案 1 :(得分:15)
在我提到user938949的回答和http://taotetek.wordpress.com/2011/02/02/python-multiprocessing-with-zeromq/之后,这是一个快速破解。如果你做得更好,请发表你的答案,我会推荐你的答案。
对于那些希望持久解决方案的人,请参考http://zguide.zeromq.org/page:all#toc64
zeromq 3.0版(beta ATM)支持ZMQ_RCVTIMEO和ZMQ_SNDTIMEO中的超时。 http://api.zeromq.org/3-0:zmq-setsockopt
zmq.NOBLOCK确保当客户端不存在时,send()不会阻塞。
import time
import zmq
context = zmq.Context()
ventilator_send = context.socket(zmq.PUSH)
ventilator_send.bind("tcp://127.0.0.1:5557")
i=0
while True:
i=i+1
time.sleep(0.5)
print ">>sending message ",i
try:
ventilator_send.send(repr(i),zmq.NOBLOCK)
print " succeed"
except:
print " failed"
poller对象可以监听许多接收套接字(请参阅上面链接的“使用ZeroMQ进行Python多处理”。我只在 work_receiver 上链接它。在无限循环中,客户端轮询间隔1000ms。如果在那段时间内没有收到任何消息, socks 对象将返回空。
import time
import zmq
context = zmq.Context()
work_receiver = context.socket(zmq.PULL)
work_receiver.connect("tcp://127.0.0.1:5557")
poller = zmq.Poller()
poller.register(work_receiver, zmq.POLLIN)
# Loop and accept messages from both channels, acting accordingly
while True:
socks = dict(poller.poll(1000))
if socks:
if socks.get(work_receiver) == zmq.POLLIN:
print "got message ",work_receiver.recv(zmq.NOBLOCK)
else:
print "error: message timeout"
答案 2 :(得分:8)
如果你使用ZMQ_NOBLOCK,发送不会阻塞,但如果你尝试关闭套接字和上下文,这一步将阻止程序退出..
原因是套接字等待任何对等体,以确保传出消息排队。要立即关闭套接字并从缓冲区刷新传出消息,请使用ZMQ_LINGER并将其设置为0 ..
答案 3 :(得分:0)
如果仅等待一个套接字,而不是创建Poller
,则可以执行以下操作:
if work_receiver.poll(1000, zmq.POLLIN):
print "got message ",work_receiver.recv(zmq.NOBLOCK)
else:
print "error: message timeout"
如果超时根据情况而变化,则可以使用它,而不用设置work_receiver.RCVTIMEO
。