RSS

Flatbuffers シリアライゼーションライブラリにおけるgRPCの標準サポートの発表

Flatbuffersのバージョン1.7の最近のリリースにより、gRPCのゼロコピーサポートが標準で提供されるようになりました。

Flatbuffersは、シリアライズされたデータに、それを展開したり追加のデータ構造を割り当てたりすることなくアクセスできるシリアライゼーションライブラリです。元々はゲームやその他のリソース制約のあるアプリケーション向けに設計されましたが、現在ではGoogle内のチームやNetflix、Facebookなどの他社でも一般的に利用されるようになっています。

Flatbuffersは、gRPCのスライスバッファをゼロコピーで直接使用することで、最大のスループットを実現します。受信したRPCはgRPCの内部バッファから直接処理でき、新しいメッセージの構築も中間ステップなしにこれらのバッファに直接書き込まれます。

これは現在、FlatBuffersのC++実装で完全にサポートされており、今後他の言語でもサポートが追加される予定です。Goにも実装がありますが、完全なゼロコピーではありませんが、それでも割り当てコストは非常に低いです(下記参照)。

使用例

どのように機能するか、例を見てみましょう。

IDLとしてFlatbuffersを使用

RPCサービスを宣言する.fbsスキーマ(プロトコルバッファに慣れている場合は.protoに似ています)から始めます。

table HelloReply {
  message:string;
}

table HelloRequest {
  name:string;
}

table ManyHellosRequest {
  name:string;
  num_greetings:int;
}

rpc_service Greeter {
  SayHello(HelloRequest):HelloReply;
  SayManyHellos(ManyHellosRequest):HelloReply (streaming: "server");
}

これをC++コードに生成するには、プロトコルバッファと同様にflatc --cpp --grpc example.fbsを実行します。

生成されたサーバー実装

サーバー実装はプロトコルバッファと非常に似ていますが、リクエストとレスポンスメッセージがflatbuffers::grpc::Message<HelloRequest> *型になります。プロトコルバッファではこれらの型がC++オブジェクトのツリーを表すのに対し、ここでは基盤となるgRPCスライスのフラットオブジェクトへのハンドルにすぎません。データに直接アクセスできます。

auto request = request_msg->GetRoot();
auto name = request->name()->str();

レスポンスの構築も同様に簡単です。

auto msg_offset = mb_.CreateString("Hello, " + name);
auto hello_offset = CreateHelloReply(mb_, msg_offset);
mb_.Finish(hello_offset);
*response_msg = mb_.ReleaseMessage<HelloReply>();

クライアントコードは、FlatBufferのアクセスと構築コードを除いて、プロトコルバッファで生成されるものと同じです。

完全な例はこちらをご覧ください。コンパイルするにはgRPCが必要です。同じリポジトリには、Go向けの同様の例があります。

お使いのプラットフォームでFlatBuffersを使用および構築する方法については、flatbuffersサイトで詳細をご覧ください。