Concurrence的文档里没有提到这个系列的方法。
我还是从unittest里找到的。
经过一番折腾,加上和作者的交流。现在大概能run的起来了。
远程调用,要使用concurrence.remote包下的RemoteServer, RemoteTasklet, RemoteClient三个对象。
过程是这样,服务端要用RemoteServer来启动一个服务,绑定到一个端口。
remote_server = RemoteServer()
server_endpoint = remote_server.serve(('192.168.1.101', 9081))
然后就是要在这个服务上注册Task,以供客户端来lookup。
(这里注册的是当前的Task)
remote_server.register('testing123', Tasklet.current())
然后开始一个循环,来监听调用:
for msg, args, kwargs in Tasklet.receive():
...
在客户端,首先要连接到服务端:
remote_client = RemoteClient()
remote_client.connect(('192.168.1.100', 9081))
找到要调用的方法:
remote_task = remote_client.lookup('testing123')
调用分为两种,同步,异步。
如果你需要返回数值,同步(阻塞的):
print MSG_SUM.call(remote_task)(10, 20, 30)
如果不需要返回,那就send吧:
MSG_TEST.send(remote_task)(30, 40)
要注意的:
1. Message对象可能需要放在Module level。这样pickle起来就。。。。
2. 作者说,最好是用stackless,greenlet有时候有问题。比如,我就碰到了_stackless.py的很多异常。
作者( Henk Punt)原话:
Looks like your using concurrence on top of greenlets and
the bug is coming from the stackless API emulation in _stackless.py
unfortunatly this emulation is not perfect yet, i have already
found/recevied several bugs in it,
so at the moment I guess it would be safer to try and use 'real' stackless....
完整的代码:
Server:
from concurrence import dispatch
remote_server.register('testing123', Tasklet.current())
def start():
if __name__ == "__main__":
dispatch(start)
Client:
from concurrence import dispatch
def client():
try:
remote_client = RemoteClient()
remote_client.connect(('192.168.1.100', 9081))
remote_task = remote_client.lookup('testing123')
MSG_TEST.send(remote_task)(20, 30)
MSG_TEST.send(remote_task)(30, 40)
MSG_TEST.send(remote_task)(20, 30)
MSG_TEST.send(remote_task)(30, 40)
MSG_SLEEP.call(remote_task)(1)
try:
MSG_SLEEP.call(remote_task, timeout = 1)(2)
except TimeoutError:
pass #expected
MSG_QUIT.send(remote_task)()
Tasklet.sleep(2)
remote_client.close()
except Exception:
logging.exception("")
def start():
client_task = Tasklet.new(client)()
if __name__ == "__main__":
dispatch(start)