PythonでgRPCのヘルスチェックを試してみる

# gRPCのヘルスチェックについて

gRPCにおけるヘルスチェックは[GRPC Health Checking Protocol
](https://github.com/grpc/grpc/blob/master/doc/health-checking.md)として仕様が定められています。
Kubernetesでは[Define a gRPC liveness probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-a-grpc-liveness-probe)に記載があるように、gRPCのヘルスチェックプロトコルを使用したLiveness Probeを指定することができます。

https://github.com/grpc/grpc/blob/master/doc/health-checking.md

https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-a-grpc-liveness-probe

仕様で定められている以下のレスポンスについてですが、レスポンスに含まれる status 0~3 の設定は`must`であり、ボディのstatusフィールド`UNKNOWN`、`SERVING`、`NOT_SERVING`、`SERVICE_UNKNOWN`の設定は`should`とされています。

```
UNKNOWN = 0;
SERVING = 1;
NOT_SERVING = 2;
SERVICE_UNKNOWN = 3;
```

> For each request received, if the service name can be found in the registry, a response `must` be sent back with an OK status and the status field `should` be set to SERVING or NOT_SERVING accordingly. If the service name is not registered, the server returns a NOT_FOUND GRPC status.

# Pythonでヘルスチェック用のサーバを立てる

gRPCのヘルスチェックプロトコルの動作確認を行うため、Pyhtonでヘルスチェックプロトコルを実装したサーバを立てます。

まずは必要なPythonのモジュールをインストールしておきます。

```bash
python -m pip install grpcio
python -m pip install grpcio-tools
python -m pip install grpcio-health-checking
python -m pip install grpcio-reflection
```

サーバ用のコードは以下の通りです。
`grpcio-health-checking`モジュールを使用することで、protoファイルからgRPCコードを生成せずに非常に簡単にヘルスチェックプロトコルを実装できます。

```python:server.py
import grpc
from grpc_health.v1 import health
from grpc.health.v1 import health_pb2
from grpc_health.v1 import health_pb2_grpc
from grpc_reflection.v1alpha import reflection
from concurrent import futures

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    health_pb2_grpc.add_HealthServicer_to_server(health.HealthServicer(), server)
    SERVICE_NAMES = (
        health_pb2.DESCRIPTOR.services_by_name['Health'].full_name,
        reflection.SERVICE_NAME,
    )
    reflection.enable_server_reflection(SERVICE_NAMES, server)
    server.add_insecure_port('[::]:5000')
    server.start()
    server.wait_for_termination()

if __name__ == '__main__':
    serve()
```


# grpcurlで動作確認をする

動作確認では[grpcurl](https://github.com/fullstorydev/grpcurl)を利用してgRPCのリクエストを送信します。

まずはprotoファイルを使用してリクエストを送信します。
protoファイルは[GRPC Health Checking Protocol
](https://github.com/grpc/grpc/blob/master/doc/health-checking.md)に記載されているものをコピペしてきます。

```protobuf:healthcheck.proto
syntax = "proto3";

package grpc.health.v1;

message HealthCheckRequest {
  string service = 1;
}

message HealthCheckResponse {
  enum ServingStatus {
    UNKNOWN = 0;
    SERVING = 1;
    NOT_SERVING = 2;
    SERVICE_UNKNOWN = 3;  // Used only by the Watch method.
  }
  ServingStatus status = 1;
}

service Health {
  rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
  rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse);
}
```

サーバを起動します。

```powershell
D:\health> python server.py

```

ターミナルからgrpcurlを実行すると`SERVING`のステータスが得られ、ヘルスチェックプロトコルが実装できていることが確認できます。

```powershell
D:\health> grpcurl -plaintext -proto healthcheck.proto localhost:5000 grpc.health.v1.Health.Check
{
  "status": "SERVING"
}

```

つづいてサーバ側で有効化したリフレクションを用いてヘルスチェックの確認をします。
```powershell
D:\health> grpcurl -plaintext -use-reflection localhost:5000 grpc.health.v1.Health.Check
{
  "status": "SERVING"
}
```