Apache Thriftの概要

Apache Thriftの概要

Apache ThriftはRPC、つまりリモートプロシージャコールのフレームワークである。Facebookで開発され、2007年4月にオープンソース化され、2008年5月にApache Incubatorへ入り、2010年11月にApache TLP (Top-Level Project) となった。Thriftは強力で、バイナリ転送が高速である。
Apache Thrift - Home

Apache Thriftのインストール

Thriftのインストールについては、次の文書で確認できる。
http://wiki.apache.org/thrift/ThriftInstallation

Ubuntuでインストールする

Ubuntuでのインストール手順をまとめると次のようになる。

  1. 必要な依存関係をインストールする。
    $ sudo apt-get install libboost-dev libboost-test-dev \
    libboost-program-options-dev libevent-dev automake libtool flex bison \
    pkg-config g++ libssl-dev
    
  2. インストールルートディレクトリへ移動する。
  3. $ ./configure
  4. $ make
  5. スーパーユーザーで次のコマンドを実行する。
    $ make install
    

Macでインストールする

Mac環境では、Homebrewを使って次のコマンドでインストールできる。

% brew update
% brew install thrift

Apache Thrift IDL

ThriftではIDL (Interface Description LanguageまたはInterface Definition Language) でインターフェースを定義し、各言語向けにソースコードを生成して実装する。

対応言語にはAs3、C Glib、C++、CSharp、D、Delphi、Erlang、Go、Graphviz、Haskell、Java、Java Me、Javascript、Node.js、Objective-c、OCaml、Perl、PHP、Python、Ruby、Smalltalkなど、24以上の言語がある。
Apache Thrift - Language and Feature Matrix

ここではThriftのIDLについて説明する。

使用できる型

Thriftでは、基本型、コンテナ型、構造体、例外型、列挙型、共用体の6種類を使用できる。

基本型

Type 説明
bool Boolean, one byte.
論理値、trueまたはfalse。
byte Signed byte.
1バイト整数。
i16 Signed 16-bit integer.
2バイト整数。
i32 Signed 32-bit integer.
4バイト整数。
i64 Signed 64-bit integer.
8バイト整数。
double 64-bit floating point value.
8バイト浮動小数点。
string String.
UTF-8でエンコードされた文字列。
binary Blob (byte array)
エンコードされていないバイトデータ。

コンテナ型

Type 説明
map<t1,t2> Map from one type to another.
一意のキーと値の組み合わせ。
C++ STL map、Java HashMap、PHP連想配列、Python/Ruby dictionaryと同義。
list<t1> Ordered list of one type.
要素のリスト。
C++ STL vector、Java ArrayList、スクリプト言語の配列と同義。
set<t1> Set of unique elements of one type.
一意な要素の集合。
C++ STL set、Java HashSet、Pythonのsetと同義。

コンテナ型の定義はC++の使い方と同じである。次は定義例である。

struct ExampleContainerDefinition
{
  1:map<i32, string> mapexample,
  2:set<i32> setexample,
  3:list<i32> listexample
}

構造体

Thriftの構造体はC言語の構造体とよく似ている。一般的な宣言は次のように行う。

struct ExampleStructure
{
  1:i32 id,
  2:string message
}

先頭に記載された値、たとえば1や2はField IDと呼ばれる。このField IDは構造体内で一意でなければならず、サーバーとクライアントの両方で構造定義が一致していることを確認するために使われる。 (別の構造体内では同じIDが存在してもよい。)

そのほか、初期値の設定や、構造体フィールドが必須か任意かを定義することもできる。初期値はフィールド名の後に=で指定できる。構造体フィールドの必須 여부はrequiredで指定し、任意の場合はoptionalを指定する。

struct ExampleStructure
{
  1: required i32 id,
  2: optional string message="default"
}

例外型

構造体と同じように、例外で使用する型も定義できる。

exception exampleException 
{
  1:i32 errorcode,
  2:string message
}

列挙型

Thriftでも列挙型を使用できる。列挙型には0から順番に値が付与されるが、任意の値を定義することも可能である。

enum exampleEnum1 {
  EnumA,
  EnumB,
  EnumC
}

enum exampleEnum2 {
  ONE = 1,
  TWO,
  FIVE = 5
}

共用体

共用体は構造体と同じように定義するが、構造体とは異なる。
共用体では、定義された複数のフィールドのうち1つのフィールドしか使用できない。 Thriftの共用体はC++の共用体と同じである。

また、この理由により共用体フィールドにrequiredは使用できない。

Services

Thriftで定義するServiceは、interfaceクラスのようなものである。 Serviceの中にはメソッドの集合を定義する。

service exampleService 
{
  void set(1:i32 key,2:string value),
  string get(1:i32 key) throws (1:i32 errorcode),
  i32 size()
}

Method

ThriftではService内にメソッドを定義できる。
MethodにはThriftで定義できる型とvoidを使用できる。
また、引数には構造体の宣言と同じように、Methodの引数内で一意なField IDを定義する必要がある。

Exception

Thriftでは例外も定義できる。

例外定義の例は次のとおりである。

exception exampleException1 
{
  1:i32 errorcode,
  2:string message
}

service exampleService 
{
  void testException1(1:string arg) throws(1:exampleException1 error),
  void testException2(1:string arg) throws(1:exampleException1 error, 2:i32 error2)
}

testException2のように複数の例外を定義することも可能である。

oneway method

Service内で定義するメソッドの中には、応答を待つ必要がないメソッドも定義できる。

oneway methodを使用する場合、戻り値は必ずvoidでなければならない。

service exampleService
{
  oneway void show()
}

その他のThrift規則

ここではThrift定義ファイルの記述規則について説明する。

コメント

コメントは次のように書ける。

/*
 コメント
*/

// コメント

ヘッダー

ヘッダーにはincludecpp_includenamespaceの3種類を使用できる。

include

includeは他のthriftファイルを使用するときに使う。 include "example.thrift"のように定義する。

cpp_include

C++を含めるには、ThriftのC++コードジェネレーターの出力にカスタムC++ includeを追加する。

namespace

namespaceは、ファイル内で定義した構造体、列挙型、Serviceが属するnamespaceを決定する。
次のように定義し、cppの部分にはphpjavaなどが入る。

namespaceで特徴的なのは、各言語に対して定義する必要がある点である。

namespace cpp hoge
namespace java hoge

定数

Thriftの定義内で定数を定義できる。

定数宣言は、型名の前にconstを付けるだけでよい。

const EXAMPLE_VALUE = 1

Typedef

Thriftの定義内で型名を変更できる。

型名の変更は、型の前にtypedefを付ければよい。

typedef ExampleType i32

フィールド名の命名規則

フィールド名に使用できるのは英字、数字、_.である。 フィールドの最初の文字は必ず英字または_でなければならない。

参照