关键逻辑说明
因为gRPC健康检查协议是借助gRPC服务实现的,所以服务端是一个常规的gRPC服务。使用Golang实现健康检查工具的话,主要逻辑就是实现一个gRPC客户端。还有一个关键的点是工具要封装为CLI(命令行工具)类型:检测到服务健康的话,执行完成后需要返回0值(命令行工具中命令执行成功返回值为0),否则返回非0值。
示例代码
下面的Golang示例代码可以直接运行,编译后可以在命令行中运行查看效果。服务端可以使用我之前的文章《gRPC服务健康检查(一):Golang项目集成服务健康检查代码》中的服务端代码,运行起来作为被检测的服务端即可。
package main
import (
"context"
"flag"
"fmt"
"log"
"os"
"os/signal"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
healthpb "google.golang.org/grpc/health/grpc_health_v1"
)
var (
addr = flag.String("addr", "localhost:50051", "the address to connect to")
// name = flag.String("name", defaultName, "Name to greet")
)
func init() {
var flAddr string
flagSet := flag.NewFlagSet("", flag.ContinueOnError)
log.SetFlags(0)
flagSet.StringVar(&flAddr, "addr", "", "the `address` to connect to")
err := flagSet.Parse(os.Args[1:])
if err != nil {
os.Exit(1)
}
fmt.Println(flAddr)
}
func main() {
retCode := 0
defer func() {
os.Exit(retCode)
}()
ctx, cancle := context.WithCancel(context.Background())
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
sig := <-c
if sig == os.Interrupt {
log.Printf("cancellation received")
cancle()
return
}
}()
dialCtx, dialCancel := context.WithTimeout(ctx, 10*time.Second)
defer dialCancel()
conn, err := grpc.DialContext(dialCtx, *addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
if err == context.DeadlineExceeded {
log.Printf("timeout: failed to connect service %q within %v", *addr, time.Second)
} else {
log.Printf("error: failed to connect service at %q: %+v", *addr, err)
}
retCode = 2
return
}
defer conn.Close()
rpcCtx, rpcCancel := context.WithTimeout(ctx, time.Second)
defer rpcCancel()
resp, err := healthpb.NewHealthClient(conn).Check(rpcCtx, &healthpb.HealthCheckRequest{Service: ""})
if err != nil {
retCode = 3
return
}
if resp.GetStatus() != healthpb.HealthCheckResponse_SERVING {
log.Printf("service unhealthy (responded with %q)", resp.GetStatus().String())
retCode = 4
return
}
log.Printf("status: %v", resp.GetStatus().String())
}
小结
这个例子只是用来简单实现了一个服务健康检查工具,逻辑并不是特别完善,希望达到一个抛砖引玉的效果。更完善的实现可以参考grpc-health-probe(
github.com/grpc-ecosystem/grpc-health-probe)这个工具的官方代码。