スプラトゥーン3で脳を破壊されたサーバーサイドエンジニアの @shuymn です。
Yappliではサービス間通信にgRPCを採用しています。gRPCでは標準のデータシリアライズフォーマットとしてProtocol Buffersがあり、Yappliでもこれを利用しています。
Yappliでの運用については紹介記事もありますのでよろしければそちらも合わせてご覧ください。
移行の経緯
Protocol Buffersのスキーマ定義ファイルから各プログラミング言語で利用するためのコード生成をするためにprotocというコンパイラが公式から提供されています。また、Protocol Buffersのスキーマ定義ファイルのLinter・Formatterとしてサードパーティ製ですが prototool があり、これらのツールを組み合わせてCIを行っていました。
prototoolのリポジトリを見ていただくと分かるとおりこちらのツールは既に開発が終了しています。そのため以下の問題が発生していました。
- prototoolはprotocに依存しているためprotocのバージョンを上げることができない
- prototoolはApple Silicon向けにビルドすることができないため、最近入社したエンジニアが手元のマシンでLint・Formatを実行できない*1
そのため新たなツールを探していたところ、Bufを見つけたのでそれに移行することにしました。
Bufについて
Bufはざっくり言うとprotocとprototoolが一体となったようなCLIツールで、開発元は最近だとConnectというgRPCのGo向けのサードパーティの実装を公開したりとgRPCエコシステムの改善に注力しているBuf Technologies, Inc.によって開発されています。
コード生成とLint・Format以外の機能もありますが、本記事では紹介しませんので気になる方は公式のドキュメントをご確認ください。
https://docs.buf.build/introduction
Bufに移行してみた所感
まずBufの使い方を理解するために公式ドキュメントにあるチュートリアルをさわりました。その上で実際に移行作業を行いましたが、Bufを使ってコード生成やLint・Formatを行うようにするのはドキュメントに書いている範囲に収まっていて特別ハマったりはしませんでした。しかし全くなにもする必要がなかったわけではないので、細かい部分になりますが紹介します。
protocで生成されるコードと差分がある
見出しの通り同じProtocol Buffersのスキーマ定義ファイルからprotocとBufそれぞれで生成されるコード*2にごくわずかに差分がありました。実際に利用する側のテストやQAで動作に問題ないことを確認した上でリリースを行い、今のところ問題は起きていません*3。
Buf Schema Registryを使うかどうか
Buf Schema Registry(以下BSR)の利用は最低限にとどめました。
最初は protoc-gen-go-grpc
などプラグインをBSR経由で利用していましたが、BSR自体まだベータ版の機能でありコミュニティによって管理されているプラグインやライブラリの更新がどこまで活発に行われるか不透明な部分があると感じたためです。そのためプラグインについては go install
したり package.json
で管理したりといったように各言語ごとに分離して管理しています。そして各種依存のインストールやコード生成はMakefileで実行するようにしました。
現在BSRを利用しているのはgoogleapisやgrpc-gatewayのようにメジャーなライブラリに絞っています。前者はBuf開発チームが公式にメンテナンスしていて、後者はgrpc-gatewayの開発チームによってメンテナンスされています。
BSRを検索して目当てのプラグイン/ライブラリがあったとしても、そのプラグイン/ライブラリの所有者ではなく第三者がForkした上でBSRにアップロードしている場合もあるので注意が必要です。
prototoolとのLintルールの差分をどうするか
Linterの設定についてはprototoolの標準的な設定よりも厳しい項目があったため、既存のパッケージについては修正が不要になるまで ignore_only
を使ってLintルールの除外をしました。その代わり、新規で追加されるパッケージについてはなるべくLintルールを除外しない方針で運用しています。
VSCodeの拡張機能の使い心地
Bufには公式でVSCodeの拡張機能がありますが、この記事を投稿した段階ではまだバリバリ使えるという感じでは無く挙動が怪しいところもありました(他のエディタ拡張については確認していません)。しかしLanguage Serverの開発も行っているようなのでより良くなっていくだろうと期待しています。
コード生成の速度
BufのGitHubリポジトリにもprotocに比べてコード生成の速度に利点があるという紹介があります。そこでCIで行っているコード生成の時間を比較すると以下のようになりました。Protocol Buffersのスキーマ定義ファイルのコード行数はライブラリを除いておよそ2万行です。
- protoc: 7〜8秒
- Buf: 5秒
なんと約150%高速化しました!
スキーマ定義の量が多くコード生成に時間がかかることが悩みの種であれば非常に魅力的なのではないでしょうか。
情報収集について
(Bufに限った話ではありませんが)BufのGitHubリポジトリのIssueでは頻繁に情報交換が行われているため、ドキュメントを読んでも分からないことがあったらまず同じような質問がされているか調べると以外とあったりするのでBufを使う場合はこちらも是非参考にしてみてください。
YappliのgRPCの今後
今回Bufに移行したことにより、Protocol Buffersとその周辺環境については最新の状態に保つことができるようになりました。そのため次はgRPCの周辺環境の更新を目論んでいます。
こちらの記事でも紹介がありますが、現在Yappliのコンテンツ管理画面とサーバーの通信にはgRPC-Webを使っていて、それを実現するためにTypeScript向けのコード生成プラグインとしてimprobable-eng/ts-protoc-genを利用しています。そもそもProtocol BuffersのTypeScriptのコード生成はデファクトスタンダードが無い状態でしたが、使っていたプラグインもとうとう更新が止まってしまいました。
そこでEnvoyの面倒を見る必要はありますが安心感がある公式のgRPC-Webを使うか、期待の新星Connectを使うかを今後様々な観点から比較検討していきたいと思っています。
おわりに
protocからBufへの移行事例、いかがでしたでしょうか。Bufはツールだけでなく開発元がgRPCエコシステムに対して情熱を持って取り組んでいるため、今後の動向も逐一追っていきたいと思います。
YappliではWebフロントエンドチーム、iOS/Androidアプリチーム、サーバーサイドチームの3チームが交わる点としてgRPCが存在しています。gRPCとその周辺環境を整備することでプロダクトに直接影響を与えるだけでなく、開発に必要なコミュニケーションがより誰でも快適に高速にできるようになるという間接的な影響も与えることができると考えています。そんな縁の下の力持ちとしてバリューを発揮できる環境が整っているYappliに興味がありましたら是非カジュアル面談しましょう!