简体   繁体   English

用Twisted阻止Thrift通话

[英]Blocking Thrift calls with Twisted

I have a Twisted/Thrift server that uses the TTwisted protocol. 我有一个使用TTwisted协议的Twisted / Thrift服务器。 I want to keep connections from clients open until a given event happens (I am notified of this event by the Twisted reactor via a callback). 我希望保持客户端的连接打开,直到发生给定事件(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.

How can I quickly return from a method of my handler object while maintaining the illusion of a blocking Thrift call? 如何在保持阻塞Thrift调用的错觉的同时快速从我的处理程序对象的方法返回?


I initialize the Thrift handler from the Twisted startup trigger: 我从Twisted启动触发器初始化Thrift处理程序:

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

My client in PHP connects with: 我的PHP客户端连接:

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

That last call ( $client->listenForEvent() ) successfully makes it over to the server and runs ServiceHandler.listenForEvent , but even when that server method returns a twisted.internet.defer.Deferred() instance, the client immediately receives an empty array and I get the exception: 最后一个调用( $client->listenForEvent() )成功将其转移到服务器并运行ServiceHandler.listenForEvent ,但是即使该服务器方法返回twisted.internet.defer.Deferred()实例,客户端也将立即收到一个空数组,我得到异常:

exception 'TTransportException' with message 'TSocket: timed out reading 4 bytes from localhost:9160 to local port 38395' 异常'TTransportException',消息'TSocket:timed out read 4 bytes from localhost:9160 to local port 38395'

You should be able to return a Deferred from listenForEvent . 您应该能够从listenForEvent返回Deferred。 Later handleEvent should fire that returned Deferred (or those returned Deferreds) to actually generate the response. 稍后handleEvent应该触发返回的Deferred(或那些返回的Deferreds)来实际生成响应。

The error you're seeing seems to indicate that the transport is not framed (Twisted needs it to be so it can know the length of each message beforehand). 您看到的错误似乎表明传输没有框架(Twisted需要这样,以便它可以事先知道每条消息的长度)。 Also, Thrift servers support returning deferreds from handlers, so that's even more strange. 此外,Thrift服务器支持从处理程序返回延迟,因此更奇怪。 Have you tried returning defer.succeed("some value") and see if deferreds actually work? 您是否尝试过返回defer.succeed(“某些值”)并查看延迟实际是否有效? You can then move to this to check that it fully works: 然后,您可以转到此位置以检查它是否可以正常运行:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM