テクニック

Protocol Buffers を扱う上でよく使われる設計パターンについて説明します。

設計や使用に関する質問は、Protocol Buffers ディスカッション グループに投稿することもできます。

よく使われるファイル名サフィックス

メッセージをいくつかの異なる形式でファイルに書き込むことはかなり一般的です。これらのファイルには次のファイル拡張子を使用することをお勧めします。

内容拡張子
テキスト形式.txtpb
ワイヤー形式.binpb
JSON 形式.json

テキスト形式の場合、.textproto もかなり一般的ですが、簡潔さのために .txtpb をお勧めします。

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

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

大規模なデータセット

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

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

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

自己記述型メッセージ

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

ただし、.proto ファイルの内容自体はプロトコルバッファを使用して表現できます。ソースコードパッケージのファイル 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 社内でそれを使用する必要がなかったためです。

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