首页 > 解决方案 > python zerorpc多线程

问题描述

我正在尝试为 python 程序构建前端服务。我选择 zerorpc 在 NodeJS 和 python 之间进行通信,效果很好,唯一的问题是我不能正确地多线程 zerorpc。
我看过几篇关于 zerorpc 和普通线程如何相互不喜欢的帖子。但是,我的后端服务已经有些先进并使用了多个线程。
所以现在的问题是,是否有可能以某种方式将普通线程和 zerorpc 两者结合起来,还是我必须重写我的主代码以使用与 zerorpc 相同的线程库?
我使用普通线程遇到的主要问题是启动服务器的线程完全冻结,因此无法再关闭。这是我目前启动服务器的方式:

self.communication_thread = Thread(target=communication_server.start_communication_server)
self.communication_thread.start()

def start_communication_server():
    global server
    addr = 'tcp://127.0.0.1:4242'
    server = zerorpc.Server(CommunicationServer())
    server.bind(addr)
    print('Created a new communicationserver running on {}'.format(addr))
    server.run()

我还尝试使用以下功能杀死服务器,但这会导致异常,这是不可取的

def kill_server():
    global server
    server.stop()

预先感谢您帮助我!

标签: pythonmultithreadingzerorpc

解决方案


zerorpc 使用 gevent 实现并发(ioloop + coroutines 等)。Gevent 是单线程的,并且在初始化之后,只能从最初用于初始化它的线程中使用。在您的情况下,这是线程调用server.run(). 因此,您只能与来自同一线程的 zerorpc 方法进行交互。

您可以使用猴子补丁(http://www.gevent.org/intro.html#monkey-patching),它可以有效地使您的Thread对象表现得像协程。如果您仅将线程用于 IO 并发,那么这可能就足够了。

否则,如果您希望线程用于 CPU 并行性,一个行之有效的解决方案是将子进程工作者用作单独的线程。您可以在主服务器和工作人员之间使用 zerorpc(unix 套接字非常适合这里)。因为工作人员无论如何都是 CPU 绑定和本地的,所以您可以禁用服务器和工作人员之间的心跳 ( Client/Server(heartbeat=0))。

但是,我找不到有关如何安全地混合系统线程和 gevent 的任何详细信息。


推荐阅读