0

我正在使用 ZeroRPC 服务器来实现服务。该服务的一些功能是长时间的 CPU 密集型任务。由于我不希望 RPC 调用阻塞,因此必须适当处理它们。考虑到 GIL,线程似乎不是一个合适的选择。我尝试过多处理,但子进程无法作为 RPC 客户端连接到另一个(不相关的)RPC 服务器。请参阅下面的代码。每次spin_off_worker()调用时,我都能够生成多个子进程,这一点很重要。在 ZeroRPC 服务器中处理/设计这些长期 CPU 密集型任务的最佳方法是什么?

RPC 服务器 #1

import zerorpc
import multiprocessing
import time
import threading

class Foo(object):

    def heavy_task(self):
        # some long processing...

        # this RPC call never gets made...
        cli = zerorpc.Client(connect_to="tcp://0.0.0.0:3334", timeout=30, heartbeat=5)
        cli.test()
        cli.close()
        return

    def spin_off_worker(self):
        s = multiprocessing.Process(target=self.heavy_task)
        s.start()
        s.join()

def start():
    s = zerorpc.Server(Foo(), heartbeat=5)
    s.bind("tcp://0.0.0.0:3333")
    s.run()
    return s

svr_proc = multiprocessing.Process(target=start)
svr_proc.start()

RPC 服务器 2

import zerorpc
import time
class Foo(object):
    def test(self):
        print "TIGR"

s = zerorpc.Server(Foo(), heartbeat=5)
s.bind("tcp://0.0.0.0:3334")
s.run()
4

1 回答 1

1

您的解决方案是正确的方向。它只需要一些调整:

  • zerorpc 需要 gevent,因此运行在协作协程环境中。因为您的工作人员(服务器#2)进程将占用 CPU 一段时间,zerorpc 将错过心跳。您可以禁用主(服务器#1)和工作人员(服务器#2)进程之间的心跳。设置heartbeat=None在两侧。

  • 由于您正在进行本地进程间通信,因此您不妨使用本地 unix 套接字(如果您可以访问系统上的 unix 套接字)。使用类似的东西unix://workers.sock。这可能比在途中拥有完整的 TCP 堆栈更有效。

无论如何,心跳在网络上比在同一台机器上本地更重要。如果想通过网络在另一台机器上运行您的工作程序,请执行以下操作:客户端机器 -> [zerorpc heartbeat] -> 服务器机器 -> [local zerorpc no heartbeat] -> 工作进程。

注意:您不必为每个 Heavy_task 调用实例化一个新的 zerorpc 客户端。您可以一遍又一遍地重复使用同一个实例。

于 2017-10-27T16:59:15.123 回答