我的设置中生成了一个Node.js子项,它创建了一个带有Python对象的双向ZeroRPC会话对。
python方面与此类似:
class MyClass:
def __init__(self, socketpath):
self.client = zerorpc.Client()
self.client.connect(socketpath)
def sendtoclient(self, msg):
self.client.receiveMessage(msg)
if __name__ == '__main__':
zpc = zerorpc.Server(MyClass(sys.argv[1]))
zpc.bind(sys.argv[1] + "_python")
zpc.run()
Node.js子客户端可以调用Python服务器上的方法,但该服务器中的客户端无法在Node.js子服务器上调用而不会出现异常:
Traceback (most recent call last):
File "/usr/lib64/python2.6/site-packages/gevent/queue.py", line 271, in _unlock getter.switch(getter)
File "/usr/lib64/python2.6/site-packages/gevent/hub.py", line 534, in switch assert getcurrent() is self.hub, "Can only use Waiter.switch method from the Hub greenlet"
AssertionError: Can only use Waiter.switch method from the Hub greenlet
<callback at 0x3055e90 args=()> failed with AssertionError
Python类中的客户端是否需要作为gevent生成,然后在需要时调用其receiveMessage
方法?还是有其他一些我忽视的技巧?
答案 0 :(得分:2)
经过一些实验,一个可行的解决方案来自Gevent的文档中的一些例子。我使用的解决方案是创建一个gevent Queue,它从服务器端填充并从循环中的单独Greenlet输出。所以在我的服务器文件中,我添加了:
import gevent
from gevent.queue import Queue, Empty
messagesOut = Queue()
def clientWorker(address):
client = zerorpc.Client()
if (None != client):
client.connect(address)
while True:
try:
messages = messagesOut.get()
client.passMessages(messages) # a method on the Node.js-side ZeroRPC server
except: # Empty could be thrown here if you're interested
pass
finally:
gevent.sleep(0)
在MyClass
中,其初始化已更改为将队列引用保留为self.outbox
(事实上,我每次访问时都可以使用全局)。当需要发送异步消息时,MyClass
会调用self.outbox.put(messages)
。
然后在创建ZeroRPC实例时向下,我产生了每个:
if __name__ == '__main__':
ge_client = gevent.spawn(clientWorker, sys.argv[1] + "_node2python")
zpc = zerorpc.Server(messagesOut)
zpc.bind(sys.argv[1] + "_python2node")
ge_server = gevent.spawn(zpc.run)
gevent.joinall([ge_client, ge_server]) # up and running here.
做到这一点解决了我的问题,作为概念验证。