gRPC C# のHealthCheck

この記事は.NET, .NET Core, monoのランタイム・フレームワーク・ライブラリ Advent Calendar 2018 - Qiita 25日目の記事です。 ほんとはGiraffeの話を書こうと思っていたけど、仕込む時間がなかったので別ネタで行きます…!

あと時間がないので色々と飛ばして書きます。

gRPCのhealth checkプロトコル

https://github.com/grpc/grpc/blob/v1.17.2/doc/health-checking.md にあるとおり、gRPCにはhealth checkプロトコルが用意されています。 これを使って例えば:

  • サーバー側でヘルスチェックに応答できるようにしておく
  • クライアントにhealthcheckコマンドを用意する
  • KubernetesのLiveness Probeでhealth checkコマンドを叩く

とかできたりします。

ライブラリインストール

公式が提供しているライブラリを使います。

https://www.nuget.org/packages/Grpc.HealthCheck/

サーバー側

使う名前空間は以下:

using Grpc.Core;
using Grpc.Health.V1;
using Grpc.HealthCheck;

他のサービスと同様にHealthServiceをサーバーに登録し、サーバー起動後にSetStatusで状態を設定してあげます。 第1引数はサービス名でいいはず。

var health = new HealthServiceImpl();
var server = new Server
{
    Services = {
        Health.BindService(health)
    },
    Ports = { new ServerPort("localhost", 50051, ServerCredentials.Insecure) }
};
server.Start();
health.SetStatus("greeter", HealthCheckResponse.Types.ServingStatus.Serving);

これで、クライアントから起動しているか確認できるようにはるはず。

クライアント側

使う名前空間は以下:

using Grpc.Core;
using Grpc.Health.V1;

クライアントはレスポンスから状態を取得して分岐させます。

Channel channel = new Channel("localhost:50051", ChannelCredentials.Insecure);
try
{
    var client = new Health.HealthClient(channel);
    var response = client.Check(new HealthCheckRequest { Service = "fanfun" });
    switch (response.Status)
    {
        case HealthCheckResponse.Types.ServingStatus.Serving:
            // 何か処理
            return;
        case HealthCheckResponse.Types.ServingStatus.NotServing:
            // 何か処理
            return;
        default:
            // v1だと他の状態はUnknownのみ
            // 何か処理
            return;
    }
} catch(Exception e) {
    // 略
}

あとは実際にサーバーを起動しつつクライアントを実行すれば結果が確認できるはず。

ところで

MagicOnionにはPingとHeartbeatサービスが組み込みで用意されています(このあたり)。 これ以外にも便利な機能があるので C# に統一できるならこっちのほうがいいかもしれません。

私は grpc-web とセットで使いたいのでMagicOnionは使えないですけどね!