使用Twisted阻止Thrift调用

时间:2011-10-19 03:22:58

标签: python twisted thrift

我有一个使用TTwisted协议的Twisted / Thrift服务器。我希望保持客户端的连接打开,直到发生给定事件(Twisted反应堆通过回调通知我此事件)。

class ServiceHandler(object):
    interface.implements(Service.Iface)

    def listenForEvent(self):
        """
        A method defined in my Thrift interface that should block the Thrift
        response until my event of interest occurs.
        """
        # I need to somehow return immediately to free up the reactor thread,
        # but I don't want the Thrift call to be considered completed. The current
        # request needs to be marked as "waiting" somehow.

    def handleEvent(self):
        """
        A method called when the event of interest occurs. It is a callback method
        registered with the Twisted reactor.
        """
        # Find all the "waiting" requests and notify them that the event occurred.
        # This will cause all of the Thrift requests to complete.

如何在保持阻塞Thrift调用的错觉的同时快速从我的处理程序对象的方法返回?


我从Twisted启动触发器初始化Thrift处理程序:

def on_startup():
    handler = ServiceHandler()                      
    processor = Service.Processor(handler)                                   
    server = TTwisted.ThriftServerFactory(processor=processor,                  
        iprot_factory=TBinaryProtocol.TBinaryProtocolFactory())                 
    reactor.listenTCP(9160, server)

我的PHP客户端连接:

  $socket = new TSocket('localhost', 9160);
  $transport = new TFramedTransport($socket);
  $protocol = new TBinaryProtocol($transport);
  $client = new ServiceClient($protocol);
  $transport->open();
  $client->listenForEvent();

最后一次调用($client->listenForEvent())成功转发到服务器并运行ServiceHandler.listenForEvent,但即使该服务器方法返回twisted.internet.defer.Deferred()实例,客户端也会立即收到一个空数组我得到了例外:

  

异常'TTransportException',消息'TSocket:timed out   从localhost:9160读取4个字节到本地端口38395'

2 个答案:

答案 0 :(得分:2)

您应该能够从listenForEvent返回延期。稍后handleEvent应该触发返回Deferred(或返回Deferreds)以实际生成响应。

答案 1 :(得分:1)

您看到的错误似乎表明传输没有框架(Twisted需要它以便它可以预先知道每条消息的长度)。此外,Thrift服务器支持从处理程序返回延迟,因此更奇怪。您是否尝试过返回defer.succeed(“某些值”)并查看延迟实际是否有效?然后,您可以转到此处以检查它是否完全有效:

    d = defer.Deferred()
    reactor.callLater(0, d.callback, results)
    return d