1
/
5

Server Reflectionが実装されていないgRPCサーバーでも簡単に叩けるCLIを作る

Photo by Nick Nice on Unsplash

はじめまして、Wantedly VisitのMatching Squadで推薦基盤の改善をしている一條です。好きな食べ物は二郎系のラーメンです。普段は推薦基盤の整備や、障害対応などをしています。そのため普段はGo、ときどきRuby, PythonでgRPCを書いています。その際にgRPCサーバのデバックが辛くなってツールを作成したのでその説明をします。

この記事は以前技術書典10でTech Bookとして出した内容を加筆・修正したものになります。

WANTEDLY TECH BOOK X:Wantedly執筆部
Wantedlyのメンバーで作った10冊目のWANTEDLY TECH BOOKです。 個々のメンバーが日々の業務で得られた知見や他のメンバーに知っておいてほしいことを1冊の本にまとめました。 過去最大ページ数の中に我々が日々行っている業務で培った知識と趣味で見つけた知見を詰め込みました。 WANTEDLY TECH BOOK は最新版を除いた電子版が無料で配布されます。 また、収録の内容は無料でオンラインで公開済みの記事や公開予定の記事を含みます。 ■目次 第1章 PoC 活用のすすめ - 社内の推論ス
https://techbookfest.org/product/4976690428116992

gRPCを叩くためには

gRPCでリクエストを送るためには.protoファイルを元にデータをエンコードしサーバに送る必要があります。そのため、

  1. 手元に.protoファイル、もしくはそこから生成されたコードを用意し、それを利用してデータをエンコードする
  2. 後述するServer Reflectionという機能を利用し、データをエンコードする

この2つのどちらかの方法を利用してリクエストを送る必要があります。

こういったことをやりやすくするために、grpc_cliやevansといったCLIがあります

grpc/grpc
This document describes the command line tool that comes with gRPC repository. It is desirable to have command line tools written in other languages roughly follow the same syntax and flags. At this point, the tool needs to be built from source, and it sh
https://github.com/grpc/grpc/blob/master/doc/command_line_tool.md
ktr0731/evans
Evans has been created to use easier than other existing gRPC clients. If you want to keep your product quality, you must use CI with gRPC testing, should not do use manual testing. Evans will complete your other use cases just like: Manually gRPC API ins
https://github.com/ktr0731/evans


これはデータをエンコードする部分をCLIとして簡単に実現できるようにしてくれていて、gRPCでもcurlなどのCLIと同じようにリクエストを送ることができるようになっています。
grpc_cliは「2」の方法で、evansは「1」と「2」の方法でリクエストが送れるようになっています。

Server Reflectionという機能は端的に説明すると、protocコマンドでサーバを生成する際に利用していた.protoファイルと同等のものを返してくれるAPIです。これにより手元に.protoファイルがなくてもエンコードを行うことができます。

ただし、このServer Reflectionは言語ごとに実装の有無は異なります。たとえばGoやPythonには実装が存在しますが、Rubyには存在しません。

社内で生じていた問題

Wantedlyでは社内のマイクロサービス間通信ではgRPCを利用しています。また多くのサービスがRubyで書かれています。

gRPC Development Environment - Wantedly の gRPC Server/Client 開発環境 | Wantedly Engineer Blog
こんにちは、Wantedly の Infrastructure Team で Engineer をしている南()です。 先日、gRPC 関連で2つのブログを書きました。「gRPC Internal」では、ドキュメントやコードを読み解くなかで見えてきた「gRPC の設計と内部実装」についてブログを書きました。「Real World Performance of gRPC」では、Wantedly で実際に gRPC を利用することで達成できたパフォーマンス改善についてブログを書きました。 今日は、より実践的な
https://www.wantedly.com/companies/wantedly/post_articles/221931

これによりほとんどのサービスではServer Reflectionが実装されておらず、手元に.proto ファイルを用意する必要があります。
この方法ではローカルの状態に依存してしまうため、具体的に次の点で自分は困っていました。

  1. 障害対応時などにデバックのためkubernetes上にPodを建ててそこからアクセスする、ということをよく行うが.protoファイルのコピーをする手間が発生する
  2. データサイエンティストにAPIを提供する際にコピペで実行できないため、まずは叩いてもらうためのステップがかなり高くなる

また、個人的に困っていた問題としてはgrpc_cliが便利で使っていたのですが、これがRubyサーバを叩くときだけ別のツールを使わなければいけない、というのがストレスになっていました。

Server Reflectionを分離する

これらの課題が自分的にはかなりきつかったため、Server Reflectionの有無に関係せず、ローカルではファイルを持たない形でデバックできるツールを作ることにしました。
また、コンセプトとしてはRubyにServer Reflectionを実装するまでのつなぎとして作ることにし、またgrpc_cliとの親和性をできるだけ保つことにしました。

ここで置いている前提としては「すべてのサービスの.proto ファイルはある1つのレポジトリに集約されている」です。
その前提ですべての.protoファイルの内容を知るServer Reflection用のサーバを生成し、それを叩くという方針にしました。
これはアイディアとしては単にServer Reflectionの機能と他のgRPC Serviceの実装を分離をする、ということをしているだけです。

そのため、次を作る必要があります。

  1. Server Reflectionが別のサーバとなる場合に対応したCLI
  2. .protoファイルからServer Reflectionを返すだけのサーバを生成するツール

実装する

rerost/giro
An alternative to grpc_cli. giro can be used for gRPC servers without Server Reflection - rerost/giro
https://github.com/rerost/giro

に実装があります。giroと書いてギロと呼んでいます。

  1. Server Reflectionが別のサーバとなる場合に対応したCLI => giro
  2. .protoファイルからServer Reflectionを返すだけのサーバを生成するツール => protoc-gen-reflection-server

と実装があります。.protoファイルからの生成はprotocのpluginとして書くほうがパースした結果が得られて楽だったのと、扱いやすかったので利用しています。
また、protoc-gen-reflection-server の挙動としては、protoc-gen-goで生成されたものを使いServer Reflectionを返すmain.goを吐くだけのものとなっています。

以下に図の中で利用している単語とその意味を書きます。

リクエストの流れとしては次のようになります。

実際に動かすと次のような形になります

$ export REFLECTION_SERVER=localhost:5000

$ giro ls
grpc.reflection.v1alpha.ServerReflection
rerost.giro.v1.HostService
rerost.giro.v1.TestService

$ giro call --rpc-server=localhost:5001 rerost.giro.v1.TestService/Echo {"message":"Test"} --metadata=key1:val1:key2:val2
{"message":"Test","metadata":{"metadata":{":authority":{"value":["localhost:5000"]},"content-type":{"value":["application/grpc"]},"key1":{"value":["val1"]},"key2":{"value":["val2"]},"user-agent":{"value":["grpc-go/1.27.0"]}}}}

実際導入してみて

Wantedlyの一部エンジニアにも導入してもらったところ、バックエンドエンジニアはもちろんデータサイエンティストにも利用してもらえています。
ただ、毎回gRPCのリクエストの中身を書くなどが面倒なので、コピペとなっているケースが多いようでしたが、目的だったコピペしやすいものを作るというのは実現できているんじゃないかなと思います。
また僕としても、もうRubyで書かれているサーバなのかGoやPythonで書かれているサーバなのかを意識しなくて済んでとても楽です。

Wantedly, Inc.からお誘い
この話題に共感したら、メンバーと話してみませんか?
Wantedly, Inc.では一緒に働く仲間を募集しています
15 いいね!
15 いいね!

今週のランキング

一條 端澄さんにいいねを伝えよう
一條 端澄さんや会社があなたに興味を持つかも