それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

gRPC を使う

gRPC について

gRPC はリモートからデータ取得、データ変更するRPCの一種

google が作って、http/2 とうまく協調するようにしている

一言でいえば、C構造体をそのままぶん投げるプロトコル

サーバーとクライアントが事前にお互いに構造を知っていれば、JSONみたいに配列にしたり、オブジェクトキーを入れなくていいよね。

乱暴に言えば、sqlite3 で1行転送してるようなもん。お互いテーブル構造を知ってれば問題ないでしょ?みたいな感じ。

準備する

├── proto
│   └── user.proto
├── protos
│   └── user.proto
├── py
│   ├── Pipfile
│   ├── Pipfile.lock
│   ├── client.py
│   ├── server.py
│   ├── user_pb2.py
│   └── user_pb2_grpc.py
└── users.json

python を準備する

PIPENV_VENV_IN_PROJECT=1 pipenv install
pipenv run pip install 
pipenv run pip3 install grpcio grpcio-tools

protoを作る

protoを作る。データベースでいうスキーマC言語でいう構造体。

proto が特徴的なのは、次の3点だと感じた。

  • protoに名前空間がある
  • proto はメソッド定義を含む
  • proto は 自身にprotoを使った参照(再帰)定義ができる

JAVAのクラス定義だとメンバとメソッド雛形が分けづらい

Cの構造体だと名前空間が使えない。

データベースのスキーマだと参照定義ができない

JSONだと冗長になりすぎる

という部分が解消されて使いやすい「データ型の定義」だと感じた。

SQLiteをリモート転送するには便利そうですよね。

server.py

自動生成されたクラスを継承して作る

client.py

自動生成されたクラスを呼び出して使う。

リクエスト実験

サーバー起動

pipenv run python server.py

クライアント側

pipenv run python client.py 1
pipenv run python client.py 2
pipenv run python client.py 3
pipenv run python client.py 10

grpcurl でリクエストを送る

grpcurl -plaintext -import-path ../protos -proto user.proto  -d ' { "id": 1 } ' localhost:1234 UserManager.get
{
  "user": {
    "id": 1,
    "nickname": "admin",
    "mailAddress": "admin@example.com",
    "userType": "ADMINISTRATOR"
  }
}

http2

http2 らしいのでtcpdump でパケットを見てみる。

f:id:takuya_1st:20220418140344p:plain

f:id:takuya_1st:20220418140414p:plain

cURLで叩きたい

HTTP/2 なので、cURLで叩けそうですが。絶対めんどくさい。

バイナリ転送が基本。まるでC構造体のようなProtoのまま転送しているので、中身を見ても仕方ないし、手動でリクエストを送るのも手間である。

どうしてもやりたきゃ、プロキシする必要がありそうです。

っていうか、冗長性を排してバイナリ転送するのがgRPCだし

参考資料

サービス間通信のための新技術「gRPC」入門 | さくらのナレッジ

https://engineering.mercari.com/blog/entry/2019-05-24-120000/