Pyzmq的eventloop.future上下文在工作线程中带有“ inproc”

时间:2018-10-15 19:33:23

标签: multithreading async-await tornado pyzmq inproc

我的应用程序的一部分由一个主线程和几个工作线程组成,这些工作线程使用pyzmq套接字将其结果发送到主线程。主线程正在运行tornado IOloop,并使用async函数来读取使用future.context创建的各种套接字类型上的传入数据。

出于性能原因,我想使用inproc协议。但是inproc仅在主线程和工作线程共享相同的上下文时才有效。另一方面,这将要求每个工作线程都需要运行tornado IOloop,我认为这对于简单的工作人员来说有点过头了。

说明问题的最小示例:

import time
from threading import Thread

import zmq
from zmq.eventloop.future import Context as FutureContext
import tornado.ioloop

def worker(ctx):
    socket = ctx.socket(zmq.PUSH)
    socket.bind('inproc://worker')

    while True:
        # Do some work
        time.sleep(2)
        socket.send_pyobj("Work done")

async def mainLoop(ctx):
    socket = ctx.socket(zmq.PULL)
    socket.connect('inproc://worker')

    while True:
        #print(socket.recv_pyobj())
        print(await socket.recv_pyobj()) 


normalCtx = zmq.Context()
futureCtx = FutureContext()

t = Thread(target=worker, kwargs=dict(ctx=normalCtx))
t.start()

# wait for bind to be effective
time.sleep(4)

io_loop = tornado.ioloop.IOLoop.current()
io_loop.spawn_callback(mainLoop, ctx=futureCtx)
io_loop.start()

在该示例中,PULL套接字不会接收消息,因为它是在与工作程序套接字不同的上下文中发出的。如果我在两个线程中都使用normalCtx(除去await),则该示例运行良好。使用TCP作为传输协议时,它也可以正常工作。

我发现要使其正常运行的解决方案是:

  1. 使用normal上下文并放弃async/await
  2. 使用future上下文并在每个worker中运行一个ioloop
  3. 使用TCP作为传输协议。

我的问题是,是否有一个魔术技巧可以使它与async/awaitinproc一起工作,而不必在工人中运行ioloops,例如通过以future的方式访问non-future上下文?

0 个答案:

没有答案