コンピューターサイエンス:アルゴリズム / OS / ネットワーク / DB
gRPC と HTTP/2 利用
「pages は数値ですか、文字列ですか」を毎回聞いている
社内でサービスを分けて作っていると、隣のチームの API を呼ぶ場面が増えます。そのたびに、項目の名前と型を確認する会話が発生します。ドキュメントはあっても、実装が変わったときに一緒に直るとは限りません。
JSON でやりとりする限り、型は約束ではなく慣習です。片方が数値を文字列に変えても、呼ぶ側は動かしてみるまで気づけません。
先に契約を書いて、両側のコードを機械に作らせる
gRPC は、この順番を逆にします。まず .proto というファイルに、やりとりする項目と呼べる操作を書きます。
プレーンテキスト
syntax = "proto3";
message Book {
string isbn = 1;
string title = 2;
int32 pages = 3;
}
service BookService {
rpc GetBook (GetBookRequest) returns (Book);
}
message GetBookRequest {
string isbn = 1;
}このファイルから、呼ぶ側と受ける側のコードを自動生成します。呼ぶ側は生成された関数を普通に呼ぶだけで、URL も本文の組み立ても出てきません。項目の名前や型を間違えれば、動かす前にコンパイルで止まります。
各項目に付いている 1 や 2 は、その項目の背番号です。転送するときは名前ではなく番号だけを送るので、title のような文字列が毎回流れません。JSON より小さく、読み書きも速くなります。
この番号は、一度使ったら二度と使い回しません。項目をやめるときも、番号は空けたまま残します。古い版のまま動いているサービスは、その番号を昔の意味で読むからです。番号を別の項目に付け直すと、片方が数値を送り、もう片方が文字列として読む、という壊れ方をします。名前を変えるのは自由ですが、番号は変えられない、と覚えておきます。
1 回の呼び出しで、何回でも返せる
gRPC は HTTP/2 の上で動きます。1 本の接続に複数の通り道を作れる性質をそのまま使うので、呼び出しの形が 4 種類あります。
| 形 | 送る | 返る | 使いどころ |
|---|---|---|---|
| 単発 | 1 回 | 1 回 | 普通の呼び出し |
| サーバー側連続 | 1 回 | 何回でも | 進捗や更新を流し続ける |
| クライアント側連続 | 何回でも | 1 回 | 大きなデータを分けて送る |
| 双方向 | 何回でも | 何回でも | 送りながら受け取る |
これらが 1 本の接続の中で同時に動きます。呼び出しごとに接続を張り直さないので、サービス同士が細かく呼び合う構成でも積み上がりが小さく済みます。
ブラウザからは、そのままでは呼べない
便利そうに見えますが、Web の画面から直接は使えません。ブラウザの JavaScript には、gRPC が必要とする低い層の操作が公開されていないからです。
回避策として、間にプロキシを 1 枚挟んで変換する方法が用意されています。ただし双方向の連続送受信は使えないなどの制約が残ります。
そのため実際には、外に公開する API は REST のまま、内部のサービス同士だけ gRPC、という分け方が多くなります。呼ぶ相手が自分たちの管理下にあり、生成したコードを両側に配れる場所でこそ、この仕組みは効きます。
復習ミニクイズ
gRPC のスキーマ定義に使う言語はどれですか