今更 Thrift を触ってみました
GoでThriftを試した。 Thrift自体が初めてだったがチュートリアル・サンプルが準備されていて簡単に利用できた。
tl;dr
Thrift はRCPを提供するミドルウェアだ。 (複数言語間を繋げる目的があり複雑なデータ構造を渡す事は考えられていない。また参照渡しなどRPCの難しい問題は避けている感じがある。)
Thfiftで責任を持つのはISO参照モデルでのプレゼンテーション層とセッション層。
この2層はThrift Architecture ではTProtocol
,TTransport
に当てはまりコンポーネントを差し替えられる様になっている。
気になった事
- TTransport でフレーミング実装がありTCPハンドシェイクを減らせる
- 公式Goライブラリでノンブロッキングサーバーがサポートされてない
- 1コネクション内で処理を多重化するのは難しい
- goroutine で対応できる可能性はある
- 1コネクション内で処理を多重化するのは難しい
- 負荷分散してくれるクライアント実装を探す必要がある
- VIPによる負荷分散はワークロードで分散できず、フレーミング利用時に注意が必要
- 言語間の差異を吸収し辛い機能はサポートされていない
- 構造体継承, ポリモーフィズム, オーバーロード, heterogeneous containers, Null return
- 参照渡し, unsigned int
読んだ資料
チュートリアルを試す
インストール
チュートリアルみたいにwget などソースからやるのが面倒なのでlinuxbrewのお世話になる。
|
|
コードジェネレート
GOPATH 配下では相対パスを利用できない事と、tutorial, shared
間で相対パスを一律で与える事が難しいため以下の様に生成するコード配置を意識して
pacakge_prefix
を与える必要がある。
|
|
チュートリアルのコードを取ってくる
go サンプルから取ってこれる。
実際に走らせる
|
|
チュートリアルコードの説明
Thrift network stackがプロトコルスタックがわかる。 4レイヤーで構成される。
レイヤー | 役割 |
---|---|
Server | 下位コンポーネントの管理を行う |
Processor | 通信のInput/Outputのやりとりを担当する |
Protocol | データのシリアライズなどを行う |
Transport | 下位レイヤ通信(TCPなど) を隠蔽する |
このうちProcessor
部分がIDLにより生成され、実処理を行うハンドラをプログラマーが実装する。
他のレイヤーはThfirt
ライブラリに含まれているのを利用する。
コンポーネントは差し替えられるようになっている。
同様の図はチュートリアルにもあったが少しイメージが違うので気にかかる。
チュートリアルとの対応
server定義箇所
server.goにある。 抜粋すると以下な感じのコードになっている。
|
|
アドレスを元にソケットを作成している(NewTServerSocket
)。
次にコードジェネレートしたNewCalculatorProcessor()
に自作したハンドラを渡してプロセッサを完成させる。
最後にNewTSimpleServer4()
に上記2つとtransportFactory
, protocolFactory
を渡しサーバーを完成させServe
メソッドでホスティングを完了している。
transportFactory
,protocolFactory
はアーキテクチャで出てきた2レイヤに対応している。
この部分は外部から与えているように差し替え可能。
チュートリアルのmain.go
からどう使うかは判断できる。
Protocol, Transport の設定方法
チュートリアルではオプションによりProtocolが変えられるように書かれている。
同じくTransportも変えられる。
当然だけどClient
,Server
の両方で同じProtocol
,Transport
を利用しないと上手く機能しない。
Transport
にはフレーミングをサポートしたもの(TFramedTransport
)が存在し別のTTransportFactory
を受け取り機能するようになっている。
フレーミングでコネクションを使い回す実装はハンドシェイクを避けられるため効率良さそうに思える。
しかし負荷分散は考えにくくなる。 L3DSRなどVIP構成を行うとコネクション単位で分散できるが実際のワークロードで分散が簡単には出来ない。 そのため複数サーバーに分散するクライアント実装があるかは調べたい。
またフレーミングをTransport
で採用してもTNonblockingServer
が公式(git.apache.org/thrift.git/lib/go/thrift
)には見当たらない。
そのためgolanlg でサーバー実装するとフレーミングを活かせなさそう。
ただメンテされていない google code内のthrift-go には
TNonblockingServer
が存在する。 読んでみると以下の様にgoroutine
を使うか否かの違いだけなので検証して問題がなければ公式にパッチを送るのを検討しても良さそう。