gRPCチュートリアルをやってみた

はじめに

マイクロサービス間の通信に使われると話題(相当流行遅れ)のgRPCを触ってみた。

実践

protocol plugin をインストールする。

$ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2

練習用リポジトリをクローンする。

$ git clone -b v1.50.0 --depth 1 https://github.com/grpc/grpc-go

練習用ディレクトリに移動しサーバーを立ち上げ、ターミナルの別タブでクライアントからリクエストを送信する。

$ cd grpc-go/examples/helloworld
# サーバー
$ go run greeter_server/main.go 
2023/01/14 10:21:19 server listening at [::]:50051
# クライアント
$ go run greeter_client/main.go
2023/01/14 10:16:14 Greeting: Hello world
# リクエスト受信時のサーバーの出力
2023/01/14 10:21:41 Received: world

メソッドを追加して、リクエストとレスポンスの型もそれぞれ定義する。

~Replyってなんか違和感がある。

// [...]
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  rpc SayHey (HeyRequest) returns (HeyReply) {}
}
// [...]
message HeyRequest {
  string name = 1;
}

message HeyReply {
  string message = 1;
}

.proto ファイルを再度コンパイルする。

先ほどインストールしたプラグインを使う。

$ protoc --go_out=. --go_opt=paths=source_relative \
    --go-grpc_out=. --go-grpc_opt=paths=source_relative \
    helloworld/helloworld.proto

ファイルが小さいからっていうのもあると思うけど、コンパイルめっちゃ速かった。

サーバー、クライアントそれぞれの実装をする。

// [...]
func (s *server) SayHey(ctx context.Context, in *pb.HeyRequest) (*pb.HeyReply, error) {
    log.Printf("Received: %v", in.GetName())
    return &pb.HeyReply{Message: "Hey " + in.GetName()}, nil
}
// [...]
// [...]
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.SayHey(ctx, &pb.HeyRequest{Name: *name})
if err != nil {
    log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetMessage())
// [...]

再度サーバーを立ち上げてリクエストを送信する。

レスポンスの結果が変わっていれば想定通り。

$ go run greeter_client/main.go
2023/01/14 10:43:40 Greeting: Hey world

正しい結果となった。

まとめ

チュートリアルに沿って触ってただけでは正直まだなんとも言えない感じではある。メリット、デメリット踏まえてサービスに取り入れていきたい。

業務で今すぐ必要な感じでもないので、歴史や背景も学び中がらゆっくり身につけていきたい所存。

参考

https://grpc.io/docs/languages/go/quickstart/