zeromq:如何防止无限期等待?

时间:2011-09-24 12:26:00

标签: python zeromq

我刚刚开始使用ZMQ。我正在设计一个应用程序,其工作流程为:

  1. 许多客户中的一个(拥有随机PULL地址)在5555向服务器发送请求
  2. 服务器永远在等待客户端PUSHes。当一个人来时,会针对该特定请求生成一个工作进程。是的,工作进程可以同时存在。
  3. 当该过程完成它的任务时,它会将结果推送给客户端。
  4. 我认为PUSH / PULL架构适用于此。请纠正我


    但我该如何处理这些情况?

    1. 当服务器无法响应时,client_receiver.recv()将等待无限时间。
    2. 客户端可以发送请求,但之后会立即失败,因此工作进程将永远停留在server_sender.send()。
    3. 那么如何在PUSH / PULL模型中设置类似超时的内容?


      编辑:感谢user938949的建议,我收到了工作回答,我正在为后人分享。

4 个答案:

答案 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