这篇文章,我们不是要讲解怎么使用 gRPC-go,或者使用 gRPC 实现一个服务。而是要讲讲如何在 gRPC-go 中完成心跳检测和健康检查。

gRPC 其实已经对如何实现心跳和健康检查有了说明了,详情见 https://github.com/grpc/grpc/blob/master/doc/health-checking.md 。而且框架已现了基本的 API 且达到基本开箱即用的程度。

原则上来说,应该很简单,只是调用 API 而已。但是,实际上呢,即使努力百度和谷歌,我们还不一定能跑起来。

protobuf

实际上呢,并不是,我们只要定义一个独一无二的 服务名 即可。

一旦跑起来之后,就发现特别的简单,真的。

只需要以下简单三步。

1. 首先定义心跳和健康检查的服务

protobuf
const HEALTHCHECK_SERVICE = "grpc.health.v1.Health"
grpc.health.v1.Health

2. gRPC-go 服务器端引入几个 module 和添加几行代码

import (
    "google.golang.org/grpc"
    "google.golang.org/grpc/health"
    healthpb "google.golang.org/grpc/health/grpc_health_v1"
)
healthgrpc_health_v1
grpc.NewServer()RegisterXXXServiceServer
s := grpc.NewServer()

// 要添加的代码 ---
healthserver := health.NewServer()
healthserver.SetServingStatus(HEALTHCHECK_SERVICE, healthpb.HealthCheckResponse_SERVING)
healthpb.RegisterHealthServer(s, healthserver)
// ---

pb.RegisterHelloServiceServer(s, hello)

其实就是添加了三行代码而已,服务器端的配置到此结束

3. gRPC-go 客户器端引入几个 module 和添加几行代码

import(
    "google.golang.org/grpc"
    _ "google.golang.org/grpc/health"
)
health
grpc.Dial()grpc.DialContext()
conn, err := grpc.DialContext(ctx,
        r.Scheme()+"://author/project/test",
        grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"HealthCheckConfig": {"ServiceName": "%s"}}`,HEALTHCHECK_SERVICE)))

conn, err := grpc.DialContext(
        r.Scheme()+"://author/project/test",
        grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"HealthCheckConfig": {"ServiceName": "%s"}}`,HEALTHCHECK_SERVICE)))
DialContext()
grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"HealthCheckConfig": {"ServiceName": "%s"}}`,HEALTHCHECK_SERVICE))

如果你还添加了其它参数,可能就是下面这个样子

conn, err := grpc.DialContext(ctx,
        r.Scheme()+"://author/project/test",
        grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s","MethodConfig": [{"Name": [{"Service": "%s"}], "RetryPolicy": {"MaxAttempts":2, "InitialBackoff": "0.1s", "MaxBackoff": "1s", "BackoffMultiplier": 2.0, "RetryableStatusCodes": ["UNAVAILABLE", "CANCELLED"]}}], "HealthCheckConfig": {"ServiceName": "%s"}}`, roundrobin.Name, *serv, *serv)),
        grpc.WithInsecure())

这里面的所有方法和变量我们都遵循惯性来的,一般你都能看懂