【问题标题】:Twisted PerspectiveBroker callRemote from wsgi webapp来自 wsgi webapp 的 Twisted PerspectiveBroker callRemote
【发布时间】:2012-01-22 09:34:19
【问题描述】:

我正在编写一个 wsgi 应用程序,它需要使用 Twisted PerspectiveBroker 来调用一些远程方法。问题是 wsgi 需要返回一个呈现的网页,但对 Twisted 服务的调用是异步的。所以基本上我的网络应用需要调用远程方法,然后做一些其他的事情,然后它必须等待远程调用完成,然后渲染页面并将其返回给客户端。

最好的方法是什么?

我目前正计划使用 Flask 来编写应用程序。

【问题讨论】:

    标签: python twisted wsgi


    【解决方案1】:

    WSGI 应用程序在它自己的线程(或进程)中运行。当在 Twisted 的 WSGI 容器中运行时,它与运行反应器的线程不同。大多数 Twisted 的 API 不是线程安全的:它们只能在反应器线程中调用。

    因此,从 WSGI 应用程序调用 Twisted API 的基本方法是使用 reactor.callFromThread,它是线程安全的,并且会导致在反应器线程中调用函数:

    ...
    reactor.callFromThread(pbRemote.callRemote, "someMethod", some, args)
    

    但是,这会丢弃您可能想要的结果。不过,在 reactor.callFromThread 之上构建一个保留结果的 API 很简单,而且在 Twisted 中也有一个实现:

    from twisted.internet.threads import blockingCallFromThread
    
    ...
    result = blockingCallFromThread(reactor, pbRemote.callRemote, "someMethod", some, args)
    

    此调用将阻塞,直到 callRemote 返回的 Deferred 触发,然后它将返回该 Deferred 的结果。

    如果你想打电话,做一些其他的工作,然后等待电话结束,你必须有点创意。您需要拨打电话并获取它返回的实际Deferred,但不要阻止它:

    resultHolder = blockingCallFromThread(
        reactor, lambda: [pbRemote.callRemote("someMethod", some, args)])
    

    然后你可以做你需要做的其他工作。当你准备好等待 PB 调用的结果时:

    result = blockingCallFromThread(reactor, lambda: resultHolder[0])
    

    这一切都比在单线程场景中使用 Twisted 更尴尬,因此使用 Twisted Web 的原生 API 确实比构建 WSGI 应用程序更容易。请记住,WSGI 的主要目标之一是允许开发可跨不同服务器(Twisted、Apache 等)移植的应用程序。如果您实际上在 WSGI 应用程序中使用 Twisted API,那么它根本不是可移植的。

    【讨论】:

      【解决方案2】:

      你可以返回 server.NOT_DONE_YET 告诉twisted.web 请求没有完成。然后调用 request.write() 和 request.finish() 来完成请求,例如:

      from twisted.web import server, resource
      
      class MyResource(resource.Resource):
          def render_GET(self, request):
              # the call will return defer, that will notify us when it finish
              d = delayCall()
              # finish the request
              def finisn_req(data):
                  request.write(data)
                  request.finish()
              d.addCallback(finisn_req)
              # tell twisted.web that this request is not finished, yet
              return server.NOT_DONE_YET
      

      【讨论】:

      • 应该提一下,我打算用Flask写webapp,除非用Twisted web方便很多。
      • 那么如何编写一个代理,使用 Twisted 接受 XML-RPC,调用你的服务器。 Flask -> XML-RPC Broker -> 你的服务器?
      猜你喜欢
      • 2011-07-29
      • 1970-01-01
      • 2013-05-09
      • 2015-03-15
      • 2018-12-15
      • 1970-01-01
      • 2010-09-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多