如何进行同步rpc调用

时间:2008-11-11 19:38:34

标签: python twisted

我正在构建一个具有本地使用类的程序,但我希望通过网络以相同的方式使用相同的类。这意味着我需要能够对其任何公共方法进行同步调用。该类读写文件,因此我认为XML-RPC开销过高。我使用twisted中的示例创建了一个基本的rpc客户端/服务器,但是我遇到了客户端问题。

c = ClientCreator(reactor, Greeter)
c.connectTCP(self.host, self.port).addCallback(request)
reactor.run()

这适用于单个调用,当收到数据时我正在调用reactor.stop(),但是如果我再进行一次调用,反应器将不会重启。还有什么我应该用的吗?可能是一个不同的扭曲模块或另一个框架?

(我没有详细说明协议是如何工作的,因为重点是我只能接到一个电话。)

附录&澄清:

我与谷歌文档分享了我正在做的事情。 http://docs.google.com/Doc?id=ddv9rsfd_37ftshgpgz

我有一个使用保险丝的版本,可以将多个本地文件夹组合到保险丝安装点。文件访问已经在一个类中处理,所以我想让服务器给我网络访问同一个类。在继续搜索之后,我怀疑pyro(http://pyro.sourceforge.net/)可能是我真正想要的(仅仅基于现在阅读他们的主页)但我对任何建议持开放态度。

我可以通过使用nfs mount并将其与我的本地文件夹组合来实现类似的结果,但我希望所有对等体都可以访问相同的组合文件系统,因此这将要求每台计算机都具有nfs服务器nfs挂载的数量等于网络中的计算机数量。

结论: 我决定使用rpyc,因为它给了我正是我想要的东西。一个服务器,它保存一个我可以操作的类的实例,就好像它是本地的一样。如果有人有兴趣我将我的项目放在Launchpad(http://launchpad.net/dstorage)上。

4 个答案:

答案 0 :(得分:2)

如果您甚至考虑使用Pyro,请先查看RPyC,然后重新考虑XML-RPC。

关于Twisted:尝试离开反应堆而不是停止反应堆,每次只需ClientCreator(...).connectTCP(...)

如果您在协议中self.transport.loseConnection(),则不会保持打开连接。

答案 1 :(得分:2)

为什么你觉得它需要同步?

如果要确保一次只发生其中一个,请通过DeferredSemaphore调用所有调用,以便对实际调用(对任意值)进行速率限制。

如果您希望能够在不同时间运行多个这些流,但不关心并发限制,那么您应该至少将反应器启动和拆除与调用分开(反应堆应该在整个生命周期内运行)该过程)。

如果你无法弄清楚如何在反应堆模式中表达应用程序的逻辑,你可以使用deferToThread并编写一大块纯粹的同步代码 - 尽管我猜这不是必需的。

答案 2 :(得分:1)

对于同步客户端,Twisted可能不是正确的选项。相反,您可能希望直接使用套接字模块。

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((self.host, self.port))
s.send(output)
data = s.recv(size)
s.close()

recv()调用可能需要重复,直到你得到一个空字符串,但这显示了基础知识。

或者,您可以重新安排整个程序以支持异步调用...

答案 3 :(得分:1)

如果你使用Twisted,你应该知道:

  1. 您不会同步拨打任何网络服务
  2. 反应堆只能运行一次,所以不要停止它(通过调用reactor.stop()),直到您的应用程序准备好退出。
  3. 我希望这能回答你的问题。我个人认为Twisted 完全是您用例的正确解决方案,但您需要解决同步性问题。

    附录&澄清:

      

    我不明白的部分原因是   当我调用reactor.run()时   似乎只是进入一个循环   观看网络活动。我如何能   继续跑我剩下的   程序虽然它使用网络?如果   我可以过去,然后我可以   可能通过   同步问题。

    这正是reactor.run()的作用。它运行一个主循环,它是一个事件反应器。它不仅会等待诱人的事件,还会等待你计划发生的任何事情。使用Twisted,您需要以处理其异步性质的方式构建应用程序的其余部分。也许如果我们知道它是什么样的应用程序,我们可以提供建议。