6

我正在把头发拉到这个上面。我正在尝试使用 zeromq 和 gevent 获得最简单的示例。我将此脚本更改为使用 PUB/SUB 套接字,当我运行它时,“服务器”套接字永远循环。如果我取消注释 gevent.sleep(0.1) 行,那么它会按预期工作并让给另一个绿色线程,在这种情况下是客户端。

问题是,为什么我必须手动添加睡眠呼叫?我认为当我导入 zmq 的 zmq.green 版本时,发送和接收调用是非阻塞的,并且在下面进行任务切换。

换句话说,为什么我必须添加 gevent.sleep() 调用才能使这个示例正常工作?在 Jeff Lindsey 的原始示例中,他正在执行 REQ/REP 套接字,并且他不需要添加睡眠调用……但是当我将其更改为 PUB/SUB 时,我需要它来让客户端进行处理。

#Notes: Code taken from slide: http://www.google.com/url?sa=t&rct=j&q=zeromq%20gevent&source=web&cd=27&ved=0CFsQFjAGOBQ&url=https%3A%2F%2Fraw.github.com%2Fstrangeloop%2F2011-slides%2Fmaster%2FLindsay-DistributedGeventZmq.pdf&ei=JoDNUO6OIePQiwK8noHQBg&usg=AFQjCNFa5g9ZliRVoN_yVH7aizU_fDMtfw&bvm=bv.1355325884,d.cGE
#Jeff Lindsey talk on gevent and zeromq

import gevent
from gevent import spawn
import zmq.green as zmq

context = zmq.Context()

def serve():
    print 'server online'
    socket = context.socket(zmq.PUB)
    socket.bind("ipc:///tmp/jeff")
    while True:
        print 'send'
        socket.send("World")
        #gevent.sleep(0.1)

def client():
    print 'client online'
    socket = context.socket(zmq.SUB)
    socket.connect("ipc:///tmp/jeff")
    socket.setsockopt(zmq.SUBSCRIBE, '') 
    while True:
        print 'recv'
        message = socket.recv()


cl = spawn(client)
server = spawn(serve)

print 'joinall'
gevent.joinall([cl, server])


print 'end'
4

1 回答 1

6

我认为当我导入 zmq 的 zmq.green 版本时,发送和接收调用是非阻塞的,并且在下面进行任务切换。

zmq.green 仅在这些调用阻塞时才会产生,如果它们准备好则不会产生(没有什么可等待的)。在您的情况下,发件人始终准备就绪,因此它永远没有理由屈服。

一些指示:

  • 最小显式收益率是gevent.sleep(0),它不需要是有限的。
  • zmq.green 仅在阻塞调用时产生。也就是说,如果一个套接字在你要求它时总是准备好发送/接收,它永远不会屈服。
  • socket.send仅在套接字未准备好发送时阻塞not (socket.events & zmq.POLLOUT)
  • 一般来说,不要相信 send 到 yield,因为 zeromq 的工作方式,除非你超出了配置的容量,否则这种情况很少发生。
  • 与 send 不同,recv在正常使用时会定期阻塞,因此它会在大多数调用中产生。但是,如果对等方正在淹没您的传入缓冲区,则重复的 recv 调用将不会屈服,直到没有任何东西可以接收,因此您可能再次需要每隔一段时间显式地屈服以防止饥饿。

zmq.green 相当于将 send/recv 变成:

try:
    socket.send(msg, zmq.NOBLOCK) # or recv
except zmq.ZMQError as e:
    if e.errno == zmq.EAGAIN:
        yield # and wait for socket to be ready, then try again

因此,如果使用 NOBLOCK 的发送/接收始终成功,则套接字永远不会屈服。

换句话说:如果一个套接字没有什么可等待的,它就不会等待。

于 2012-12-16T21:38:02.847 回答