grpc-go(https://github.com/grpc/grpc-go) resolverのメモ
確認したバージョン
- go 1.22
- google.golang.org/grpc v1.63.2
resolverとは
- gRPCのresolverはクライアントがサーバー発見するために使用されるコンポーネント
サービス名を実際のネットワークアドレス(IP アドレスとポート)に解決する役割を担っている
ライブラリから提供されるresolver
- ライブラリ(grpc-go)からdns, passthrough, unix, unix-abstractの4種類のresolverが提供されている
- どのresolverを使うかはgrpc.ClientConnを生成するgrpc.NewClientとgrpc.DialContextのtarget引数に渡すURL schemaで判定される
DNS resolverを使用したい場合はdns://server.grpc.demo
- schemaを指定しない場合...
- grpc.ClientConnをgrpc.NewClientで生成すると、デフォルトでschema "dns"として扱われる
- grpc.ClientConnをgrpc.DialContextで生成すると、デフォルトschema "passthrough"として扱われる
- デフォルトのschemaを変更したい際はgrpc.ClientConn生成前に↓のように設定しておく必要がある
Go
resolver.SetDefaultScheme("passthrough")
DNS resolver
- DNS resolverでもgrpc.DialOptionで↓のようにload balancingを設定することで、DNSから返ってきた複数IPアドレスをload balancingすることができる
Go
grpc.WithDefaultServiceConfig(`{"loadBalancingConfig": [{"round_robin":{}}]}`)
custom resolver
- 自前のresolverを登録できる
- 例えばAWS Cloud Mapを使用したい場合はaws-cloudmap-grpc-name-resolverのようなコードが参考になる
- この場合はDNS名前解決ではなく、Cloud Mapの機能でサーバー発見する
- つまりCloud Mapのインスタンスの検出設定に"DNSクエリ"は不要で、"API呼び出し"のみがあれば良い
resolverの挙動
- resolver.ResolverのResolveNowメソッドはgRPCコネクションが切れたタイミングなどで呼ばれる
- サーバーのインスタンスやpodが増えた際はResolveNowは呼ばれない
つまりスケールアウトしたインスタンスにはリクエストされず、適切にload balancingされない - 対応方法の1つとしてサーバー側で↓のようにkeepalive.ServerParameters.MaxConnectionAgeを設定する
Go
s := grpc.NewServer(grpc.KeepaliveParams(keepalive.ServerParameters{ MaxConnectionAge: 10 * time.Minute, MaxConnectionAgeGrace: 30 * time.Second, }))