因此,我在一个pet项目中使用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()

一切正常我的理解是这两个实现应该是等价的,但不知怎么的,它们不是。
有什么想法吗?

最佳答案

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套接字的遗迹上调用recv什么都不会来,zeromq已经死了。
如果不进行测试,我只能猜测在新进程中完全运行zerorpc应该可以工作:
def ZeroRPC_Service():
  server = zerorpc.Server(FuncWrapper())
  server.bind(server_address)
  server.run()

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

然后,通过一些管理器对象或多进程提供的其他共享内存服务,您可以使新进程中的zerorpc服务器访问并与本地进程共享数据。
另一方面,如果您要做的是在不阻塞的情况下调用server.run(),如果您只使用gevent,我会告诉您只需在它自己的协同程序中运行它:
server = zerorpc.Server(FuncWrapper())
server.bind(server_address)
server_coro = gevent.spawn(server.run)

也许您可以直接从tornado coroutine/asyunc函数调用server.run。也许有办法把gevent和tornado结合起来(就像这个链接建议的那样:https://bmmh.wordpress.com/2012/10/07/tornado-and-gevent/),我不知道在这一点上有什么帮助。

08-27 06:21