app/grpc_services
_grpc_service
, GrpcService
という suffix を付与しますapp/pb_serializers
_pb_serializer
, PbSerializer
という suffix を付与しますProfileService
の BatchGetProfiles
という RPC の処理を見てみましょう。 以下のように、apis で生成された gRPC Service Class である W::UsersPb::ProfileService::Service
を継承した ProfileGrpcService
Class で、 batch_get_profiles
method を実装します。 この例は簡略化して書いてますが、実際にはメソッド内でDB への問い合わせるなどして意味のあるデータを保持したオブジェクトを作成、 最終的に W::UsersPb::BatchGetProfilesResponse
オブジェクトとして返します。req
はリクエストメッセージで、 call
は呼び出しに関する情報を持つ GPRC::ActiveCall
^grpc-activecallのオブジェクトです (正確には GRPC::ActiveCall::SingleReqView
または GRPC::ActiveCall::MultieReqView
のどちらか)。call.matadata
とするとメタデータが取得することができます。Profile
object の serializer であれば以下のように実装できます。GRPC::BadStatus
^grpc-badstatus というエラークラスを raise することでクライアントにエラーを返すことになります。 また、エラーコードごとに GRPC::BadStatus
のサブクラスが用意されており、それを利用することも出来ます。 以下2行は同じ意味になります。google.rpc.Code
^google-rpc-code に定義されている Protobuf の Enum になります。 エラーコードの使い分けなどについてはprotobufスキーマとgRPC通信を参照してください。GRPC::BadStatus
と Google::Rpc::Code
を利用することでメッセージとエラーコードからなる単純なエラーを表現することは出来ました。 しかし、これでは実際のアプリケーションで表現力が足りません。 例えば単純なフォームのバリデーションエラーでも、フィールドごとにエラーメッセージを保持できる必要があります。google.rpc.Status
のうち、 Any の配列である details
にエラーの詳細を詰めることが可能です。 Google API Design Guide の Errors では google/rpc/error_details.proto に定義されるメッセージの利用が推奨されており、Wantedly でもそれに則っています。.new_rpc_error
という関数が提供されており、それを使うと便利です。GrpcTesting
module^grpc-testing (private library) の利用を検討するといいでしょう。app/grpc_services
に定義した「gRPC Service Class を継承した Class」を Handler として登録する必要があります。また、Wantedly では、マイクロサービスは Kubernetes 上で Docker Container として動かしているので、Heath Check の為に gRPC Health Checking Protocol を実装した Handler の登録も必要です。その他、Observability を高めるための gRPC interceptor(gRPC の拡張機能。後述するが、Rack Middleware 相当のもの)の設定なども行う必要があります。grpc-server
コマンドは以下のように利用することができます。.stub_for
という「gRPC Client 生成用のメソッド」を用意しています。.stub_for
の実装はだいたい以下のようになっています。 元々、HTTP/1.1 の通信では servicex gem の中で Faraday Middleware などの設定を行なった API Client を提供する様にしていました。 .stub_for
は同様の体験を gRPC でも提供することが意図されています。 Observability を確保するための interceptor のセットや User Agent の設定なども .stub_for
で自動で行われるようになっています。:deadline_exceeded
です。 また、サーバー側に原因があると考えられる UNKNOWN, INTERNAL, UNAVAILABLE を :server_errors
でまとめて指定できるようにしています。errors: [:server_error, :deadline_exceeded]
を書くことをまず考えるのが良いプラクティスでしょう。コードレビューの際にも、そのことをチェックしてください。