マイクロサービスや自作ミドルウェアのAPIをメンテナブルにしたいよねっていう文脈で、OpenAPIやGraphQL、gRPCといった技術が採用されるのを最近よく目にする。
バックエンドを実装しているWebエンジニアとしては、こういう仕組みが整備されつつあるのはありがたい。APIをシステムの外に公開しようとすると、ドキュメンテーション/バリデーション/クライアントの実装など、意外と副次的な作業が必要なので、、汎用化されたツールに頼れるのは助かる。マイクロサービスを用いたアーキテクチャを考えるにあたっても、システム間のアダプタをイメージしやすくなる。
そういう背景で、最近家ではgRPCを調べている。このあとはgRPCについて調べたことのメモや感想のコーナーになっているので、興味があったらどうぞ。
主な情報源
だいたいこのへんを眺めておくと、gRPCの基本については抑えることができる。
- grpc / grpc.io
- gRPCの概要が説明されているだけでなく、プログラミング言語ごとの実装チュートリアルも充実している
- protocコマンドで生成されるgRPCのserverやclientの実装のドキュメントもここでまとめて読める
- Developer Guide | Protocol Buffers | Google Developers
- Protocol Buffer についてはここをみる
- protoの言語仕様もここにある
- GitHub - grpc/grpc: The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)
- gRPCのserverやclientを生成するツールや生成されるコードなどが入ったリポジトリ
- 主な対応プログラミング言語の実装はすべてここに入っている
- GitHub - grpc/grpc-go: The Go language implementation of gRPC. HTTP/2 based RPC
- なぜかGoの実装だけはここにある(go getの事情?)
- gRPC Ecosystem · GitHub
- いろんなgRPCのグッズがあつまるオーガニゼーション
- awsome-grpc もこのオーガニゼーション内にあって、grpc.ioにラインナップされていないプログラミング言語の対応ライブラリとかはこのへんから探してみると良い
試しにコードを書いてみた
自分でprotoを定義して、gRPCのプログラミングを体験してみた。
いくつかの言語でgRPCのサーバ/クライアントを実装してみたかったので、同じメソッドを実装したgrpcサーバをたくさん立てると、勝手に連携して動作するような構成にしてみた。コードはGitHubに置いてある。Dockerを使って試せるようになっているので、make build && make up
とすると動いているところが見れる。
全体を管理するBossプロセスとその元で働くMemberプロセスがいて、以下のような感じで動作する。特に何かの役に立つというモノではない。
- Bossプロセスを起動する
- いくつかのMemberプロセスを起動する。Memberプロセスは起動したらBossプロセスのJoinメソッド呼び出す、このシステムに参加する
- Boss プロセスはしばらくMemberプロセスの参加を待ったあと、Memberプロセスの順序を決める。
- Bossプロセスは決めた順番になるように、各Memberプロセスに対して、そのプロセスの次のプロセスを指定するSetNextメソッドを呼び出す。循環するように一番最後のMemberプロセスの次のプロセスは最初のプロセスになるようにしておく
- Bossが最初のMemberに対してPokeメソッドを呼び出す。MemberプロセスのPokeメソッドを呼び出すと、そのMember次のMemberのPokeを呼び出すようにしておく
- 一度投入されたPokeメソッドの呼び出しは連鎖して無限に呼び出され続ける
本当は、gRPCのサーバとクライアントを10言語で実装してみた結果www みたいな感じでレポートしようとしたけど、似たような実装を繰り返すだけみたいな雰囲気になったので途中で飽きて終わった...。
感想
- データ型とメソッドのシグニチャのみでRPCのインタフェースを定義できるのが簡潔で良い
- クエリやPOSTされたメッセージとデータ型との対応をちまちま定義する必要がない
- RPCのドキュメントとしてみたときも分かりやすい
- プログラミング言語ごとにprotocで生成されるgRPCサーバの実装モデルがまちまちなので注意する
- 共通のgRPCサーバ実装というのはなく、各プログラミング言語ごとに丁寧に実装されている(それぞれの言語の実装を眺めるとおもしろい)
- 実装モデルを理解して利用しないとパフォーマンスの問題が起こるかもしれない(PythonやRubyではGILに注意するとか)
- PHP ではそもそもサーバの実装がなかったりした
- プログラミング言語ごとにprotocで生成されるgRPCクライアントの機能がまちまちなので注意する
- Pythonのクライアントでは非同期にgRPCのメソッド呼び出しをして結果をfutureで得たりできておもしろい
- 静的型付けのプログラミング言語と相性が良い印象
- Protocol Bufferで定義したmessage型と、gRPCを実装しているプログラミング言語上の型との間に直接対応があるとわかりやすい
書いてみた中では、Goと相性が良かったように思う。Google文化圏の技術同士だからという感じはある。
次のアクション
ひとまずシンプルなサーバとクライアントを実装しただけなので、もう少し進んだトピックにも取り組んでみる
- ストリーミング
- gRPCはストリーミングでメッセージを送受信できるので体験してみる
- ロードバランシング/冗長化
- 実際のシステムで利用するにはロードバランシングや冗長化が必要になる。gRPC的には一つのトピックみたいなので調べてみる
- GCPだといい感じのグッズがあるだとか、AWSのALBと相性が悪いっぽいとかの噂を聞く
- grpc-gateway
- gRPCはバイナリプロトコルということもあって、gRPCに対応しづらいシステムからアクセスできなかったり、気楽にcurlで試せなかったりする
- gRPCのメソッドにそれぞれ対応するREST APIを生やしてくれるグッズがあるらしいので試してみる。実運用ではどうせこういうのが必要そう
- 意味のあるgRPCを喋るアプリケーションの開発
- もうちょっと現実味のある課題に出会えるかもしれない