【gRPC】gRPCで登場するProtocol Buffersとprotoファイルって何?
背景
gRPCに関して何となくで理解していたので改めて自分の知識のアップデートと棚卸しを目的にメモします。どちらかというと企業の技術ブログをかき集めたのでリンク集として見ていただけますと幸いです。
gRPCとは
- Googleで開発された多言語間のRemote Procedure Call(RPC)を実現するプロトコル
- IDLとしてはProtocol Buffersが使われている
- 通信にはHTTP/2の枠組みが利用されている
色々な記事を拝見すると上記3つについて取り上げられていることが多かったです。今回はProtocol Buffers
について掘り下げていこうと思います。
Protocol Buffersとは
Protocol Buffers は構造化データを定義する IDL としての役割(※1)と、その構造化データをネットワーク経由で送信可能なバイト列へシリアライズする機能、またその逆のデシリアライズする機能(※2)を備えています。(Protocol Buffersはデータをシリアライズする際に、JSONやXMLのようなテキスト形式ではなくバイナリ形式にシリアライズします)
※1,Protocol Buffersはデータのシリアライズとインターフェースの定義に活用することができるGoogleが開発したインタフェース記述言語(IDL)
です。
※2,Protocol Buffersは構造化データをバイト列に変換(シリアライズ/デシリアライズ)するためソフトウェアなので、構造化データを変換するためのスキーマ言語
という捉え方もできます。
※googleの公式ドキュメントより引用
Protocol buffers are Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data
公式にも記述されている通り「Protocol Buffersとは、構造化データをシリアライズするための、言語やプラットフォームに依存しない拡張可能なメカニズム」そのものの事で、実態としてProtocol Buffersというものがあるわけではないようです。
スキーマ言語のメリット
protoファイルにてスキーマ定義を行い、ツールを使ってコード生成ができるのでクライアント・サーバーそれぞれでこのprotoファイルを共有すると「一方に修正が入ったタイミングでもう一方も修正する手間」や「変更後に全体への共有やドキュメントの更新をし忘れてフロント・サーバー間での仕様のズレが発生する問題」が解消されます。
以前フロント側でAPIの修正をサーバー側に依頼し、だいぶ時間が経った後にサイレントで直してもらってフロント側で原因不明のエラーとなって帰ってきた経験があるのでスキーマファーストで開発メンバー間での認識にずれがなくなるのは大きなメリットだと感じました。
- googleの公式ドキュメント
https://developers.google.com/protocol-buffers/ - スマートキャンプ
https://tech.smartcamp.co.jp/entry/grpc-and-protobuf-servey - ラクスル
https://tech.raksul.com/2020/12/02/comfortable-api-development-with-protocol-buffers/
protoファイルとは
Protocol Buffersはprotoファイルという専用のフォーマットで記述します。service(gRPCのAPI定義)とmessage(スキーマの定義)を記述することができ、protoファイルを作成後はprotocというコンパイラを使ってprotoファイルを任意のプログラミング言語に変換する必要があります。(後述)
service
service サービス名 {
rpc メソッド名 (引数のメッセージ型) returns (返り値のメッセージ型) {}
}
message
message メッセージ型の名前 {
型 フィールド1 = 1;
型 フィールド2 = 2;
型 フィールド3 = 3;
}
protoファイルの具体例
全体を通して書くとこんな感じになります。
syntax = "proto3";
package example.protobuf;
service UserService {
rpc GetUser(UserRequest) returns (UserResponse);
}
message UserRequest {
string id = 1;
}
message UserResponse {
User user = 1;
}
message User {
string id = 1;
string name = 2;
int32 age = 3;
}
protoファイルをコンパイルする
# users_pb.rb が生成される
protoc users.proto --ruby_out=.
最後に
ここまででgRPCのProtocol Buffersについて理解が深まったかと思います。当初自分はProtocol Buffersとprotoファイルの違いが分からなかったのですがここまでご覧いただいていると下記の意味がわかってくるのではないでしょうか?
※「スターティングgRPC」から引用
gRPCではシリアライズフォーマットとしてProtocol Buffersを使います。Protocol Buffersでは.protoを拡張子としてもつファイル上にスキーマ定義を行い、protocコマンドで各言語用のコードを生成します。したがって、gPRCでもこの.protoファイル上に、Protocol Buffersの仕様に基づいてスキーマ定義をおこなう必要があります。
Protocol Buffersでデータのスキーマ(message, service)を定義して(protocで)自動生成したコードを利用することで、言語やプラットフォームに依存することなくアプリケーション間で構造化データを簡単に読み書きすることが可能になります。
色々と調査を進めていくとQiitaやZennではなく企業の技術ブログで取り上げられているケースが多く、マイクロサービスを展開している企業を追っていくとかなりgRPC周りのキャッチアップがしやすかったです。
実装編はまた別途取り上げることにします。
参考記事
- Wantedly
https://docs.wantedly.dev/fields/system/apis - サイボウズ
https://github.com/ymmt2005/grpc-tutorial - メルカリ
https://engineering.mercari.com/blog/entry/2019-05-31-040000/ - MEDLEY
https://developer.medley.jp/entry/2020/08/21/190934
Discussion