読者です 読者をやめる 読者になる 読者になる

TwistedでThriftのクライアント/サーバーを書く

Twisted Thrift

TwistedでThriftのクライアント/サーバーを書くには"--gen py:twisted"オプションをつけてモジュールを生成する必要がある。PyPIに上がっているのは大抵"--gen py:new_style"のようなオプションで生成したモジュールだから知らないとハマる。

scribeのインターフェイスをもつクライアントとサーバーを書く例。Thriftとfb303は/usr/localにインストールされているとする。

$ thrift -I /usr/local/share --gen py:twisted /path/to/scribe.thrift

でscribe.thriftからモジュールを生成。

クライアントは、

#import sys
#sys.path.insert(0, '/path/to/gen-py.twisted')

from twisted.internet import reactor, defer
from twisted.internet.protocol import ClientCreator

from thrift.transport import TTwisted
from thrift.protocol import TBinaryProtocol

from scribe import scribe

@defer.inlineCallbacks
def say_hello(proto):
    res = yield proto.client.Log([scribe.LogEntry(category='greeting',
                                                  message='Hello World\n')])
    print res
    reactor.stop()


d = ClientCreator(reactor,
                  TTwisted.ThriftClientProtocol,
                  client_class=scribe.Client,
                  iprot_factory=TBinaryProtocol.TBinaryProtocolFactory(),
                  ).connectTCP('localhost', 1463)
d.addCallback(say_hello)

reactor.run()

サーバーは、

#import sys
#sys.path.insert(0, '/path/to/gen-py.twisted')

import zope.interface
from twisted.internet import reactor
from thrift.transport import TTwisted
from thrift.protocol import TBinaryProtocol

from scribe import scribe
from scribe.ttypes import ResultCode

class ScribeHandler(object):
    zope.interface.implements(scribe.Iface)

    def Log(self, messages):
        print messages
        return ResultCode.OK

if __name__ == '__main__':
    processor = scribe.Processor(ScribeHandler())
    factory = TTwisted.ThriftServerFactory(
        processor=processor,
        iprot_factory=TBinaryProtocol.TBinaryProtocolFactory())
    reactor.listenTCP(1463, factory)
    reactor.run()

のようになる。

sys.path.insertでthriftコマンドで生成したgen-py.twistedの場所を指定しているが、PYTHONPATHで指定したり、virtualenvで非Twisted版モジュールと混ざらないような環境を作っておいた方がいいかもしれない。

ちなみに、上のサーバーのコードのような非常に単純なコードでscribeのnetwork storeが簡単に作れる。scribeで大量のデータを集めてそれを解析するとなるとHDFSを使ったほうがいいと思うが、自分でScribeのインターフェイスをもつサーバーが作れれば役に立つこともありそうだ。