Overview
proto から gRPC クライアントを生成して、サービスを呼び出すときにリトライ設定を入れたいケースで service config を使った話です。
gRPC の service config とは
サービスを呼び出す時に必要になる timeout や retry の設定を gRPC のコネクションレベルで設定できます。
設定は https://github.com/grpc/grpc-proto/blob/master/grpc/service_config/service_config.proto#L44 を見ると分かりやすいです。
実装としては以下のようになります。
service config 側
// ref: https://github.com/grpc/grpc-proto/blob/master/grpc/service_config/service_config.proto type ServiceConfig struct { MethodConfig []MethodConfig `json:"methodConfig"` } // MethodConfig はメソッドごとの設定です。 type MethodConfig struct { Name []MethodName `json:"name"` RetryPolicy *RetryPolicy `json:"retryPolicy,omitempty"` } // MethodName は対象となるサービス/メソッドを指定します。 type MethodName struct { Service string `json:"service"` Method string `json:"method,omitempty"` } // RetryPolicy はリトライポリシーの設定です。 type RetryPolicy struct { MaxAttempts int `json:"maxAttempts"` InitialBackoff string `json:"initialBackoff"` MaxBackoff string `json:"maxBackoff"` BackoffMultiplier float64 `json:"backoffMultiplier"` RetryableStatusCodes []string `json:"retryableStatusCodes"` } // DefaultRetryableStatusCodes は一般的にリトライ可能なステータスコードです。 var DefaultRetryableStatusCodes = []string{ "UNAVAILABLE", "RESOURCE_EXHAUSTED", "DEADLINE_EXCEEDED", "ABORTED", "INTERNAL", "UNKNOWN", } // WithRetryPolicy は ServiceConfig から grpc.DialOption を生成します。 func WithRetryPolicy(cfg ServiceConfig) grpc.DialOption { b, _ := json.Marshal(cfg) return grpc.WithDefaultServiceConfig(string(b)) }
grpc.DialOption を connection にアタッチすることで retry 設定をサービスに入れることができます。
conn = libsgrpc.NewClient(addr, "serviceName", libsgrpc.WithRetryPolicy(libsgrpc.ServiceConfig{ MethodConfig: []libsgrpc.MethodConfig{ { Name: []libsgrpc.MethodName{ {Service: "サービス名は完全修飾名にする (後述)"}, }, RetryPolicy: &libsgrpc.RetryPolicy{ // ここに設定する }, }, }, }), )
ハマったところ
指定するサービス名は proto の完全修飾名にする
これがハマりました。ServiceConfig を設定する対象のサービスを指定するときは proto の完全修飾名 にする必要があります。
最初リトライ設定しても動かず、テストコードを確認すると proto に定義されたサービスの設定の仕方がわかりました。
https://github.com/grpc/grpc-proto/blob/master/grpc/testing/test.proto#L24-L30 で定義されたサービスへの Service Config の設定は https://github.com/grpc/grpc-go/blob/master/test/retry_test.go#L64-L74 のように grpc.testing.TestService になります。
まとめ
リトライ処理自体は自作することもできますが、gRPC を使っているなら gRPC が用意してる機能に乗っかるのもいいなと思いました。