- gRPCでは、Protocol Buffersのフォーマットでシリアライズしてデータのやり取りを行う。
-
.proto
ファイルにてスキーマ定義を行い、ツールを使ってコード生成ができる。そのため、クライアント・サーバーそれぞれでこの.protoファイルを共有できれば、仕様のズレなく開発をすすめることが可能。 - この記事では、.protoファイルの文法をざっとまとめてみる
サンプル全体
// バージョン定義
syntax = "proto3";
// パッケージ定義
package sample;
// import
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
// サービスとRPCメソッド定義
service SampleService {
rpc Sample (SampleRequest) returns (SampleResponse);
// サーバーストリーミングRPC
rpc SampleServerStreamMethod (SampleRequest) returns (stream SampleResponse);
// クライアントストリーミングRPC
rpc SampleClientStreamMethod (stream SampleRequest) returns (SampleResponse)
// 双方向ストリーミングRPC
rpc SampleBidirectionalMethod (stream SampleRequest) returns (stream SampleResponse)
}
message SampleRequest {
string name = 1;
}
message SampleResponse {
Sample sample = 1;
}
// メッセージ型
// 右の数字は「タグナンバー」
message Sample {
// スカラー型
// 数値、文字列、真偽値、バイト配列がある
int32 id = 1;
string name = 2;
bool isBool = 3;
// deprecated 廃止予定かつ非推奨であるフィールドを明示する
string duplicated_field = 4 [deprecated = true]
// reserved識別子 廃盤にしたタグナンバー
reserved 7, 8, 10 to 12;
// リスト(配列)
// 多次元配列は定義できない
repeated SampleList sample_list = 5;
// マップ(連想配列)
map<string, string> sample_map = 6;
// 複数の中からどれかひとつ
oneof message {
string one = 1;
string other = 2;
}
// Well Known Types
google.protobuf.Duration sample_duration = 9;
google.protobuf.Timestamp create_time = 13;
// 列挙型
enum SampleEnum {
UNKNOWN = 0;
TEST1 = 1;
TEST2 = 2;
TEST3 = 3;
}
}
バージョンの定義
syntax = "proto3";
パッケージの定義
- 他の.protoファイルで定義したメッセージを使うときなどに、名前の衝突を避けるためにパッケージ名を設定できる
package sample;
import
- 他の.protoファイルで定義したメッセージ型を使いたい場合に使う
- ここではGoogleがつくった.protoファイルをimportしている
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
サービスとRPCメソッド
- APIの定義本体
- SampleServiceというサービスを定義
- SampleRequestを引数に取り、SampleResponseを返すSampleというメソッドを定義している
- ストリーミングにしたい場合は引数、戻り値にstreamをつける
- 単方向ストリーミング
- サーバーストリーミングRPC(戻り値にstreamを設定)
- サーバー側が複数のレスポンスを非同期で返す
- クライアントストリーミングRPC(引数にstreamを設定)
- クライアント側から複数のリクエストを非同期で送り、サーバー側は1つのレスポンスを返す
- サーバーストリーミングRPC(戻り値にstreamを設定)
- 双方向ストリーミング
- 引数、戻り値の両方にstreamをつける
service SampleService {
rpc Sample (SampleRequest) returns (SampleResponse);
// サーバーストリーミングRPC
rpc SampleServerStreamMethod (SampleRequest) returns (stream SampleResponse);
// クライアントストリーミングRPC
rpc SampleClientStreamMethod (stream SampleRequest) returns (SampleResponse);
// 双方向ストリーミングRPC
rpc SampleBidirectionalMethod (stream SampleRequest) returns (stream SampleResponse);
}
スカラー型
- 数値、文字列、真偽値、バイト配列がデータ型としてある
- デフォルト値
データ型 | デフォルト値 |
---|---|
string | 空文字 |
bytes | 空配列 |
bool | false |
数値 | 0 |
enum | 最初に定義された値。必ず0にする |
メッセージ型 | 実装依存 |
repeated | 空配列 |
メッセージ型
- 複数のフィールドを持った型
- タグナンバー
- フィールドの右側の数字。
- 同一メッセージ内で一意にしなければならない
- reserved識別子
- フィールド削除などで廃盤にしたタグナンバーを記載する
- deprecatedオプション
- 廃止予定かつ非推奨のフィールドを明示する
message Sample {
// スカラー型
// 数値、文字列、真偽値、バイト配列がある
int32 id = 1;
string name = 2;
bool isBool = 3;
// deprecated 廃止予定かつ非推奨であるフィールドを明示する
string duplicated_field = 4 [deprecated = true]
// reserved識別子 廃盤にしたタグナンバー
reserved 7, 8, 10 to 12;
// 〜 中略 〜
}
リスト(配列)
- 型の前にrepeatedをつけることで配列を定義できる
- スカラー型・メッセージ型ともに使用可能
- 多次元配列は定義できない
// リスト(配列)
// 多次元配列は定義できない
repeated SampleList sample_list = 5;
マップ(連想配列)
- キーには整数値、文字列、真偽値のみ使える
- mapは配列にできない
map<string, string> sample_map = 6;
列挙型
- 型の前にenumをつけることで列挙型を定義できる
// 列挙型
enum SampleEnum {
UNKNOWN = 0;
TEST1 = 1;
TEST2 = 2;
TEST3 = 3;
}
oneof
- oneofをつけることで、複数のものから1つという定義ができる
- ここでは
one
かother
を返すメッセージ型になる
oneof message {
string one = 1;
string other = 2;
}
Well Known Types
- Googleが定義したメッセージ型
- 日時・期間や、戻り値を返さないことを表すものなどがある
google.protobuf.Duration sample_duration = 9;
google.protobuf.Timestamp create_time = 13;
コードの生成
- 上記で定義した.protoファイルをもとに、クライアント・サーバーの両サイドで各言語用のprotocコマンドを使ってボイラープレートコードを生成する