4

因此,我正在使用 ZeroRPC 和 Tornado 进行一个宠物项目,并且在将 ZeroRPC 与python的多处理库结合使用时遇到了一些问题。具体来说,我正在以编程方式创建和运行新的 ZeroRPC 服务器,但通常在运行时,zerorpc服务器会阻塞,所以我的想法是将它扔到另一个进程中,如下所示:

 server = zerorpc.Server(FuncWrapper())
 server.bind(server_address)
 process = multiprocessing.Process(target=server.run)
 process.start()

但是,当我这样做时,调用RPC服务器只是挂起,这是未正确实例化端点时的典型行为。但是,如果我只是让服务器运行阻塞并像这样调用它:

 serhouldver = zerorpc.Server(FuncWrapper())
 server.bind(server_address)
 server.run()

一切正常。我的理解是这两个实现应该是等价的,但不知何故它们不是。

有任何想法吗?

4

1 回答 1

0

zerorpc 使用 gevent 进行协作异步 IO。您可能想了解龙卷风、多处理和 gevent 是如何一起发挥作用的。

对于我可以说的:

server = zerorpc.Server(FuncWrapper())
server.bind(server_address)
process = multiprocessing.Process(target=server.run)
process.start()

第 1 行和第 2 行在当前进程上创建和绑定端口。但在第 3 行和第 4 行,我猜想发生的是:

  • 调用fork,进程中的所有线程都丢失在fork中
  • 任何 zeromq 套接字和上下文现在都死了(不再有线程)。好消息是,上下文可以被破坏,并创建一个新的(参见http://lists.zeromq.org/pipermail/zeromq-dev/2014-January/024536.html)。
  • 现在,您在本地进程上打开了一个端口,并带有一个活动的 zeromq 套接字,但没有人从这个套接字读取(因此当您与它交谈时没有反应)。
  • 另一方面,在多进程的进程中,zerorpc 正在运行,在原来的zmq socket 的relics 上调用recv。什么都不会发生,zeromq 已经死了。

如果没有测试,我只能猜测在新进程中完全运行 zerorpc 应该可以工作:

def ZeroRPC_Service():
  server = zerorpc.Server(FuncWrapper())
  server.bind(server_address)
  server.run()

process = multiprocessing.Process(target=ZeroRPC_Service)
process.start()

然后通过一些Manager对象或多进程提供的其他共享内存服务,您可以使新进程中的zerorpc服务器访问并与您的本地进程共享数据。

附带说明一下,如果您想要做的是调用 server.run() 而不阻塞,如果您只使用 gevent,我会告诉您简单地在它自己的协程中运行它:

server = zerorpc.Server(FuncWrapper())
server.bind(server_address)
server_coro = gevent.spawn(server.run)

也许您可以server.run直接从龙卷风协程/异步函数调用。也许有一种方法可以整合 gevent 和 tornado(就像这个链接建议的那样:https ://bmmh.wordpress.com/2012/10/07/tornado-and-gevent/ ),我不知道如何帮助你这点。

于 2015-04-03T06:09:03.187 回答