見出し画像

gRPCをより便利に使えるBufを触ってみる

初めに

最近、マイクロサービスを構築する際のサービス間の通信としてgRPCを採用するケースが増えてきたように感じます。(今回はgRPCについてはある程度知っている程で進めていきます。)
その中でprotoファイルを書いてコードを生成することになると思うのですがコマンドはどのようになっていますでしょうか?設定にもよると思いますが結構長いコマンドになり覚えることは難しいと思います。実際に自分が開発を行っているサービスでもコマンドはMakefileにまとめたりしています。
また、スキーマ駆動ならではの課題だとは思うのですがクライアントとサーバーで生成されたコードのバージョンが正しいかどうかはどのように管理していますでしょうか?スキーマの管理はどのように行っているでしょうか?
などなどgRPC自体はメリットも多くマイクロサービス間の通信として採用率は上がってきてはいるもののまだ不便なことが多い状態です。

そこで、今回はBufを触ってどのように便利になるのかと言ったことを調査してみます。もしよければこの技術をプロジェクトで取り入れたりすることを考えたいと思っています!
Bufの公式サイトは以下です。

今回は軽くチュートリアルを進めてみてもしよかった場合は別の記事でさらに深堀していきたいと思っています!
Introductionから読んでいきます。(各目次がリンクになっているので参照してください。)

Introduction

いきなりですがこのページの1行目のschema-driven paradigmがリンクになっていて記事に飛ぶのですが言語は静的になったもののサービス間の通信はまだ動的で今はこう言った解決があるものの曖昧になってと言った背景が描かれていて面白かったので読んでみると良いと思います!

解決しようとしている課題について→APIデザイン・必要な依存物の簡単な確保・バージョン違いによる生合成の確保・スタブの作成・エコシステムの反映(ここら辺かなり雑にまとめているので実際に読むことをお勧めします)

これらの課題解決を実現するためにBufを開発しているみたいで現在2つほどソフトウェアがあるみたいです。CLIとBSRです。

とりあえず触ってみないとわからないのでCLIから触っていきます。インストールしてからツアーを進めてみます。ツアーは20分程度で終わるみたいです。

Installation

自分はBrew経由で行きます。

brew install bufbuild/buf/buf

ではツアーを進めていきます!

Tour

1. Configure and build

手順通りツアー用のリポジトリをクローンして移動します。

git clone https://github.com/bufbuild/buf-tour
cd buf-tour/start/petapis

まずbufはprotoファイルのコンパイルに必要な情報を全てyamlファイルに書いていくみたいです。雛形がコマンドによって生成できるみたいなので作っていきます。これによりbuf.yamlが生成されます。

buf mod init

goのコマンドと似てますね。
これはprotoファイルがあるディレクトリに配置してプロジェクトのルートディレクトリにはそのワークスペースを定義したbuf.work.yamlを配置するみたいです。

ビルドは以下のコマンドでできるみたいです。

buf build

特にエラーもなく実行できました。ただ設定も何も書いていないのでおそらくただ走らせて何もしていないだけだと思います。

2. List all Protobuf files

コマンド一つでコンパイル予定のprotoファイル一覧を表示させたりすることができるみたいです。
これ必要なものがしっかりコンパイル対象になっているか確認したい時に便利かもしれないです。

buf ls-files

引数にgithubのリポジトリを指定することもできるみたいです。

3. Lint Your API

protoファイルのLint機能もついてきます。自分達が作っているものでも1行空けるかだったり設定の順番だったり人によって変わってくるのでこう言ったLintがあるのありがたいですね。
Lintの設定自体はbuf.yamlに書くみたいです。

4. Detect breaking changes

大きな変更があるときの検知ができるみたいです。

5. Generate code

一番知りたかったことですね。生成に関する設定はbuf.gen.yamlに書くみたいです。チュートリアル通りに書いてみます。
C++, JavaのコードでGoはまた後の章で紹介されるみたいです。ただ生成用のコマンドはわかりました。

buf generate ディレクトリ名

6. Log into the BSR

実際にBSRのアカウントを作っていきます。ドキュメントに従ってログイン。

7. Push a module

いくつか今後出てくる専門用語をまとめてくれているので自分もまとめておきます。
Modules:protobufファイルの集まり(つまり外部からコピペしたものは含まれないみたいです)
Repositories:モジュールが保存される場所。Gitと違ってリモートにのみ存在してクローンという概念はないみたいです。
モジュールにはその保存場所のDNS・所有者・リポジトリ名を含むみたいです。

手順に従ってpushすると自分のリポジトリにドキュメントが表示されたり現在の最新のコードが表示されるようになりました!

8. View generate documentation

先ほど見てしまったのですがprotoのドキュメントについて紹介されています。githubで言うところのREADMEのようなものも追加することができるみたいです!

9. Add a dependency

BSRを使わない状態で他のProtobufのAPIを使う場合は手動で行う必要があるよ
→自分もよくvalidation用のものとかは手動で行っていて最初は手間取ったのを思い出しました。
BSRはnodeでいうnpmのような働きをすると言ったイメージでよさそうですかね?

今回はgoogleapisを使いたいとして手順としてはbuf.yamlのdepsの中にgoogleapisを記述して以下のコマンドを打つことによってインストールされるみたいです。

buf mod update

実行してみたところbuf.lockが生成されました。ビルドも正常に通りますがどうやら元々あったdatetime.protがないです。もしかしてコンパイルごとにネットから拾ってきているのかと思ったのですがその下の説明で書かれていました。
module cacheというところに保存されているみたいで自分のmacの場合 .cache/buf の中を辿っていったらdatetime.protoが入っていました。
これでプロジェクト毎にprotoをgitから引っ張ってきてコピペして、、、と言った操作を行う必要がなく、さらに更新も自動でおこなってくれるようになりました!
もちろん勝手にバージョンがあったら困ると言ったこともあると思うのですがそれもしっかり対応されていてバージョン固定の方法もドキュメント内に記載されています。

10. Generate Go code

ついにGoのコードを生成していきます。
自分はgRPCはGoでしか使わないのでこの章を読んでいきますが書かないのであれば読む必要はないかと思います!
ドキュメントの通りにbuf.gen.yamlを書き換えていきます。(チュートリアルだから退けているのかわかりませんがrequire_unimplemented_serversってtrueで良い気がします。)

その後にコードを生成していきます!

buf generate buf.build/$BUF_USER/petapis

これbuf generateだけでも動くのではと思ったのですが動かなかったです。ローカルに依存するコードが入っていると思うのですがもしかしたらbuf.lock依存先がリモートになっていたからかもしれないです。ではなぜローカルにコードをキャッシュする必要があるのかと聞かれたら謎です。考察なので間違っているかもしれませんがbuf.lockを元にリモートに問い合わせて何かのバージョン情報なりを一旦受け取ってローカルにあるとわかったらローカルのものを使っていると言った感じなんですかね?
とりあえず無事にgoのコードは生成されました!

11. Implement gRPC endpoints

特に特別なことはしていないので省略
コードのコピペだけします。

12. Use a workspace

開発が進むにあたりprotoファイルを変更したりしたときにどのような操作を行う必要があるのかやワークスペースの使い方について説明してくれるみたいです。
ワークスペースを設定することによって簡単に他のディレクトリからprotoの型を持ってきたりすることができるようになるみたいです。
lintの機能だったりも一つの機能でワークスペース内のproto全てを確認させることもできるみたいです。

13. Use managed mode

protoファイルでは例えばgoの生成したい場合go_packageというオプションをつけると思うのですがそれ自体は生成するAPIに直接関わってくるコードではないと思います。この章ではmanagedモードを使ってそのオプションを書かずともコード生成を可能にする方法を紹介してくれるみたいです。
managedモードの場合protoにデフォルトで定義しているパッケージ名がgoでのパッケージ名になりそうです。また外部のprotoに関しては自動定義にした場合ローカルを3章してしまうことになるので外部参照にするためにもexceptタグを使ってやる必要があるみたいです。
これで自動でパッケージ名を付けることができ現状のprotoファイルにはAPIに直接関係のある要素のみになった気がします。

14. Push workspace modules

今まで作ったpayment関係のprotoファイルをBSRに上げる方法が載っています。ワークスペースを使った場合ローカルで生成などはできるのですがBSRには変更が同期されない?みたいで個別にpushしてやる必要があるみたいです。ワークスペース単位で上げられたら良いのだがと思ったのですがマイクロサービスを想定した場合にサービス一個に対してprotoも一つになることが多いのであまり問題ないいと言った感じなんですかね?

これ以降はまとめだったり応用なので今回はここで終わります!

使ってみての感想

今後もBufを使って行くべきか

結論から書くと実際にサービスを作ってみて今後最終判断をしていきたいと感じました。結構前向きな感じでいて取り入れるメリットは大きいと思っています。CLIに関して簡単なコマンドでコード生成できたりLintができたりと便利です。

一方今回のツアーをとおしてもBSRのメリットがあまり理解できなかったと感じています。外部protoの依存関係を自動的に解決できたりというのはわかったのですが自分が作ったコードをBSRに上げることによるメリットが理解できなかったです。ドキュメントが生成されたりバージョン管理ができたりというのはわかるのですがそれはBSRを使わなくてもできます。BSRを入れないと受けることのできないメリットに関してはわからなかったです。
一つ思いついたのはバージョンをサービス間で統一できるから?これに関しては実際のサービスに取り入れてみないとツアーだけでは判断ができないというふうに感じました。(またみた感じプライベートリポジトリを作ろうとした場合有料になるのでそれも一つの懸念点です。)

導入コスト

これも結構重要な判断基準だと思いますがそこまで高いという印象は持ちませんでした。そこまで依存関係で引っかかったりしてしまうこともないような気はしました。いくつか単語がが出てくるのとファイル名に関してさえ理解できたら導入コスト自体は高くないような気がしています。

この記事が気に入ったらサポートをしてみませんか?