gRPCに入門する
業務で gRPC を使ったプログラムを見かけて何も知らないな〜と思ったから入門してみる。
概要、利点/欠点、利用シーンを学び、簡単なコードを書いてみる。
まずは公式サイトのトップページをざっと見てみる。
gRPC:任意の環境で実行可能な高性能でオープンソースの Remote Procedure Call の(以下、RPC)フレームワーク。
らしいが、今のところほぼ何も分かっていない。
RPC:ネットワークを介した先の処理を呼び出す
くらいの理解(で合っている?)だが、「任意の環境で実行可能」と言える理由、「高性能」と言える理由のか分からない。
もう少し読むと(英訳が合っていれば)以下のような内容が書かれていたので、ほんのりなんとなく上記理由が分かった気がする。
- デバイス、モバイルアプリ、ブラウザをバックエンドサービスに接続するための分散コンピューティングに適用可能(=任意の環境で実行可能?)
- Protocol Buffer というものでサービス(?)を定義
- 一行書くだけでランタイムと開発環境をインストールでき、フレームワークによって数 million/s の RPC ができるまでスケールする(=高性能?)
- 様々な言語やプラットフォームのサービス向けに idiomatic なクライアントと stub サーバーを自動生成
- 双方向のストリーミングと完全に統合された pluggable な認証
次は以下を読む。
gRPC は Protocol Buffer を インタフェース定義言語として、かつメッセージのフォーマットとして利用する。
RPC のシステムと同様に、gRPC も以下の考え方をベースにしているらしい。
- サービスを定義
- パラメータと戻り値の型と共に遠隔で呼び出すメソッドを指定
サーバーサイドでは、上記インタフェースを実装してクライアント側の呼び出しを扱うために gRPC サーバーを実行する。
クライアントサイドでは、サーバーと同じメソッドを提供する stub を持ち、stub からサーバーサイド側のgRPC サーバーにリクエストを送り、レスポンスを受け取る。
クライアント・サーバーサイド共に、gRPCをサポートしている言語で実装できる。
Protocol Buffer: Google の構造化データをシリアライズするための仕組み
- シリアライズ対象のデータを
.proto
形式のファイルで以下のように定義する。
これを Protocol Buffer では message と呼ぶ。
message Person {
string name = 1;
int32 age = 2;
}
- Protocol Buffer compiler(以下、protoc)で上記 message をコンパイルして好みの言語向けにデータにアクセスするクラスを生成する。そのクラスでは各フィールドに対する getter, setter 相当のメソッド(
age
でいうところのage()
,set_age()
)が提供される。アプリケーションの実装で生成したクラスを利用する。
次はgRPC のアークテクチャと RPC のライフサイクルの概要を学ぶ。
gRPC では、Protocol Buffer で サービスを定義する。
サービスのメソッドは4種類ある。
- Unary RPC(単一のリクエストを送り、単一のレスポンスを返す)
- Server streaming RPC(クライアントがリクエストを送り、サーバーがメッセージの列を読むためのstreamを返す)
- Client streaming RPC(クライアントがstreamを使ってメッセージの列を書き込んで送り、サーバーがstreamを読んでレスポンスを返すまで待つ)
- Bidirectional streaming RPC(クライアントとサーバーが読み書きできる stream を使って message を互いに読み書きする)
ライフサイクルの話もあったが、実際に実装する時に学ぶことにする。
利用シーン
https://grpc.io/docs/what-is-grpc/faq/#why-would-i-want-to-use-grpc に書いてあった。
- 低レイテンシでスケーラブルな分散システム
- クラウドのサーバーと通信するモバイルクライアントの開発
- 正確で効率的で言語と独立している必要のある新しいプロトコルの設計
- 認証や負荷分散、ロギングやモニタリング等の拡張を可能にするための階層的な設計(?)
なんとなく分かってきたところで実際にコードを書いていく。
Rust で実装する。Rust の gRPC ライブラリとして tonic がデファクトスタンダードっぽいのでこれを使う。
tonic の Get Started の、Protocol Buffer でごく簡単なサービス(リクエスト中の文字列をほぼそのまま返す)を定義し、サーバー側を実装して grpcurl でリクエストしてレスポンスが返るところまで確認。
クライアントも実装してリクエストできることを確認。
この後は、gRPCを使ったシステムの実例を調べて何か簡単に作れないか検討する。
チャットアプリを使う事例を多く見つけたのでこれをやってみる。
アプリ関係ないが、grpc-gateway(gRPC の RPC 定義を HTTP API にマッピングするための protoc のプラグイン)があるらしい。後でこれも触る。
https://zenn.dev/yoshd/articles/47fd56dc4f863e を読んで gRPC サーバーの実装方法を学んだ後、https://qiita.com/kawamou/items/96d815b41c4c27e4537b 等のチャットアプリ実装記事を参考にする方針で進める。