Rails + SpringBootでgRPCする方法について色々調べた
RailsのバックエンドとしてSpring Bootを置いてgRPCでやりとりするみたいなのをどう実現するかを調べている
RubyからgRPCを使う
クライアント側はこれが参考になった。proto
からGemの中身を生成して配布するの良さそう。
クライアント側でgRPCを扱うコードはこんな感じになる
stub = Snip::UrlSnipService::Stub.new('0.0.0.0:50052', :this_channel_is_insecure) req = Snip::SnipRequest.new(url: 'http://shiladitya-bits.github.io') resp_obj = stub.snip_it(req)
Spring BootでgRPCを使う
これを使うのが楽そう。 @GRpcService
のアノテーションを付与するだけで、 Spring
と gRPC
を共存させることができる。
@GRpcService public static class GreeterService extends GreeterGrpc.GreeterImplBase{ @Override public void sayHello(GreeterOuterClass.HelloRequest request, StreamObserver<GreeterOuterClass.HelloReply> responseObserver) { final GreeterOuterClass.HelloReply.Builder replyBuilder = GreeterOuterClass.HelloReply.newBuilder().setMessage("Hello " + request.getName()); responseObserver.onNext(replyBuilder.build()); responseObserver.onCompleted(); } }
実際にアプリケーションを作るにあたって
クライアントをどこで作るか
.proto
からクライアントをどこで作って配布するかみたいなのを考えていた。 .proto
を vendoringするためのツールを作っている方もいるみたい。
現在のところはgradleのビルドの中でRubyクライアントを作っている。クライアントが決まっていて1言語だけなら、これがコスパよいかなという気がする。
このgradleのプラグインで、Rubyクライアントも生成できそうなんだけど、なぜかCLIで grpc_tools_ruby_protoc -Iproto --ruby_out=lib --grpc_out=lib proto/*.proto
としたときにできる *_services_pb.rb
が生成されない。
このIssueと関連ありそうな気がするけど、コードまでは追えてない。
しょうが無いので、無理やりgradleの中でコマンドを実行してRubyのクライアントを生成するようにしている。 キレイにやるならCIで生成するとかかなぁ。
エラーハンドリング
まだ良くわかってないが、この辺を読んで見るつもり。というか、この公式のexamplesもっと早く見ておけばよかった・・・
色々資料を読んでいると、エラーの詳細を返したいときはメタデータに入れるのが一般的なのかなー。例えばバリデーション的なものをやりたいときに、gRPCからどんな風にエラーを返せばいいんだろ。
grpc/examples/ruby/errors_and_cancellation at master · grpc/grpc · GitHub
今のところの感想
なんとなく行けそうなイメージは出てきたけど、まだまだ色々調べなきゃいけないことが多い。
gRPCだけでなく、SpringBootやgradleとかもまだまだ「全然わからない。俺は雰囲気で(ry」って感じなので、ちゃんと作っていくとまだまだ色々ありそうな予感。