はじめに
最近、GoでgRPCサーバーの開発をするきっかけがありました。今回は、helthcheckのエンドポイント /grpc.health.v1.Health/Check
の開発を通してGoでgRPCサーバーの実装からECSへのデプロイまでまとめていきます。
gRPCやProtocol Buffersの詳細な概念については今回は割愛しますが、興味があれば2年前にまとめた記事もご覧いただければと思います。
ツールのインストール
まず最初に、開発に必要なツールをインストールします。以下は、必要なツールの一覧です。
go install google.golang.org/protobuf/cmd/protoc-gen-go
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc
go install github.com/grpc-ecosystem/grpcurl/cmd/grpcurl
protoファイルからコードを自動生成する
次に、Protocol Buffersの定義を含む .proto ファイルからGoのコードを自動生成します。以下は、helthcheck用のprotoファイルとコード生成のコマンドです。
syntax = "proto3";
package grpc.health.v1;
option go_package = "pb/grpc_health_v1";
message HealthCheckRequest {
string service = 1;
}
message HealthCheckResponse {
enum ServingStatus {
UNKNOWN = 0;
SERVING = 1;
NOT_SERVING = 2;
SERVICE_UNKNOWN = 3;
}
ServingStatus status = 1;
}
service Health {
rpc Check(HealthCheckRequest) returns (HealthCheckResponse) {}
}
protoc --go_out=. --go-grpc_out=require_unimplemented_servers=false:. proto/health.proto
gRPCサーバーの実装
生成されたコードを基に、gRPCサーバーの実装を行います。以下は簡単な例です。
package main
import (
"context"
"net"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"github.com/ymktmk/golang-grpc/pb/grpc_health_v1"
)
type HealthHandler struct{}
func NewHealthHandler() *HealthHandler {
return &HealthHandler{}
}
func (hc *HealthHandler) Check(ctx context.Context, req *grpc_health_v1.HealthCheckRequest) (*grpc_health_v1.HealthCheckResponse, error) {
return &grpc_health_v1.HealthCheckResponse{
Status: grpc_health_v1.HealthCheckResponse_SERVING,
}, nil
}
func main() {
listen, err := net.Listen("tcp", ":50051")
if err != nil {
panic(err)
}
grpcServer := grpc.NewServer()
reflection.Register(grpcServer)
healthHandler := NewHealthHandler()
grpc_health_v1.RegisterHealthServer(grpcServer, healthHandler)
if err := grpcServer.Serve(listen); err != nil {
panic(err)
}
}
grpcurlで動作確認
実装が完了したら、grpcurlを使用してサーバーの動作を確認します。以下は、grpcurlを使用してhealthcheckを行う例です。
grpcurl -plaintext localhost:50051 grpc.health.v1.Health/Check
ECSへのデプロイ
TerraformでECSへデプロイします。唯一異なるのは以下の3点です。
- matcher = "0"
- protocol_version = "GRPC"
- path = "/grpc.health.v1.Health/Check"
matcher = "0"とするのは、HTTPのステータスコードにあたる概念がgRPC Codeであり、成功はOK = 0
です。
resource "aws_lb_target_group" "lb_target_group" {
name = "gRPC-ALB"
port = 50051
protocol = "HTTP"
protocol_version = "GRPC"
vpc_id = aws_vpc.vpc.id
target_type = "ip"
health_check {
enabled = true
healthy_threshold = "3"
unhealthy_threshold = "2"
interval = "30"
matcher = "0"
timeout = "5"
path = "/grpc.health.v1.Health/Check"
port = "traffic-port"
}
}
おわりに
今回は、helthcheckのエンドポイント /grpc.health.v1.Health/Check
の開発を通してGoでgRPCサーバーの実装からECSへのデプロイまでまとめました。皆さんの参考になれば幸いです。