テクニック

Protocol Buffers を扱う上で一般的に使用される設計パターンについて説明します。

設計や使用に関する質問は、Protocol Buffers 討論グループに送ることもできます。

一般的なファイル名サフィックス

メッセージを様々なフォーマットでファイルに書き込むことはかなり一般的です。これらのファイルには以下のファイル拡張子を使用することをお勧めします。

内容拡張子
テキストフォーマット.txtpb
ワイヤーフォーマット.binpb
JSON フォーマット.json

特にテキストフォーマットについては、.textproto もかなり一般的ですが、簡潔さから .txtpb をお勧めします。

複数のメッセージのストリーミング

複数のメッセージを1つのファイルまたはストリームに書き込む場合、あるメッセージがどこで終わり、次のメッセージがどこで始まるかを追跡するのはあなた次第です。Protocol Buffer のワイヤーフォーマットは自己区切りではないため、Protocol Buffer パーサーはメッセージの終わりを単独で判断できません。この問題を解決する最も簡単な方法は、メッセージ自体を書き込む前に各メッセージのサイズを書き込むことです。メッセージを読み戻す際には、サイズを読み取り、次にバイトを別のバッファに読み取り、そのバッファからパースします。(バイトを別のバッファにコピーするのを避けたい場合は、CodedInputStream クラス (C++ と Java の両方にあります) をチェックしてください。これは、特定のバイト数に読み取りを制限するように設定できます。)

大規模なデータセット

Protocol Buffers は、大規模なメッセージを処理するようには設計されていません。一般的に、1メガバイトを超えるメッセージを扱っている場合は、別の戦略を検討する時期かもしれません。

そうは言っても、Protocol Buffers は、大規模なデータセットの個々のメッセージを処理するのに優れています。通常、大規模なデータセットは小さな断片の集まりであり、各小さな断片は構造化されたデータです。Protocol Buffers がデータセット全体を一度に処理できないとしても、各断片をエンコードするために Protocol Buffers を使用すると、問題が大幅に簡素化されます。これで、構造のセットではなく、バイト文字列のセットを処理するだけで済みます。

Protocol Buffers には、大規模なデータセットをサポートする組み込み機能は含まれていません。なぜなら、状況によって異なる解決策が必要となるからです。単純なレコードのリストで十分な場合もあれば、データベースのようなものが必要な場合もあります。各ソリューションは個別のライブラリとして開発されるべきであり、それが必要な人だけがコストを支払う必要があります。

自己記述型メッセージ

Protocol Buffers は自身の型に関する記述を含んでいません。したがって、対応する .proto ファイルで型が定義されていない生のメッセージだけが与えられた場合、有用なデータを抽出することは困難です。

ただし、.proto ファイルの内容自体は、protocol buffers を使用して表現できます。ソースコードパッケージの src/google/protobuf/descriptor.proto ファイルは、関連するメッセージタイプを定義しています。protoc は、--descriptor_set_out オプションを使用して、.proto ファイルのセットを表す FileDescriptorSet を出力できます。これにより、次のように自己記述型プロトコルメッセージを定義できます。

syntax = "proto3";

import "google/protobuf/any.proto";
import "google/protobuf/descriptor.proto";

message SelfDescribingMessage {
  // Set of FileDescriptorProtos which describe the type and its dependencies.
  google.protobuf.FileDescriptorSet descriptor_set = 1;

  // The message and its type, encoded as an Any message.
  google.protobuf.Any message = 2;
}

DynamicMessage (C++ および Java で利用可能) のようなクラスを使用することで、SelfDescribingMessage を操作できるツールを作成できます。

この機能が Protocol Buffer ライブラリに含まれていない理由は、Google 社内でこの機能を使う必要がなかったためです。

この技術は、ディスクリプタを使用した動的メッセージのサポートを必要とします。自己記述型メッセージを使用する前に、プラットフォームがこの機能をサポートしていることを確認してください。