テクニック

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 Buffer を使用して表現できます。ソースコードパッケージの 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 内部でそれを使用する必要がなかったためです。

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