簡単にgRPCを実施してみた
gRPCとは
gRPC(Google Remote Procedure Call)は、Googleによって開発されたオープンソースのリモートプロシージャコール(RPC)フレームワークです。RPCは、ネットワーク上で異なるシステムやプログラム間での相互作用を可能にするプログラミングモデルです。
そして、gRPCはクライアントとサーバー間で効率的な通信を実現するために、Protocol Buffers(protobuf)を使用します。Protocol Buffersは、データのシリアライズとデータ構造の定義を行うための仕組みであり、効率的なデータの交換を可能にしています。
gRPCとHTTPの比較
特徴 | gRPC | HTTP API |
---|---|---|
プロトコル | HTTP/2 | HTTP |
フォーマット | protobuf | JSON |
詳細な比較はこちら
開発環境
windows 10
go 1.20
protoc 23.3
環境構築
windowsの環境構築に苦労したので、つまずきそうなポイントを上げていきます
Protocol Buffers 導入
Protocol Buffersをインストール際のときMacの方はbrewで簡単に済むと思うのですが、windowsの場合は下記のGithubからダウンロードしてbinファイルにpathを通してください
おそらくパスを通したあとパワーシェルではコマンドを実行できますが、vscodeではうまくいかないと思います。自分の解決策としては再起動することで正常に稼働しました。
$ protc --version
libprotoc 23.3
gRPCの導入
$ go get -u google.golang.org/grpc
Protocol Buffers の Go プラグインを導入
参照したサイトで多くの場合下記のコマンドが書かれてます
$ go get -u github.com/golang/protobuf/protoc-gen-go
しかし推奨されていないと返ってきます
go: module github.com/golang/protobuf is deprecated: Use the "google.golang.org/protobuf" module instead.
現在では次のやり方が推奨されてます
$ 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
gRPCの実施
今回はチュートリアルにもある簡単なチャットアプリを作りたいと思います!
/gRPC_chat
ディレクトリを作りました。
go modの作成
go mod init grpc-go-chat
protoファイルの作成
このprotoファイルに定義を書くことによって、protoファイルを実行することでサーバーとクライアントの雛形を作ることができます。
/gRPC_chat/chat
にchat.protoを作成します
syntax = "proto3";
package chat;
option go_package="./chat";
message Message {
string body = 1;
}
service ChatService {
rpc SayHello(Message) returns (Message) {}
}
protoファイルの実行
protoファイルを実行することによって、/gRPC_chat/
にchat_grpc.pb.go
が作成されます
$ protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./chat/chat.proto
サーバーの作成
/gRPC_chat
にメッセージを返すメソッドの作成
package chat
import (
"context"
"log"
)
type Server struct {
UnimplementedChatServiceServer
}
func (s Server) SayHello(ctx context.Context, in *Message) (*Message, error) {
log.Printf("Receive message body from client: %s", in.Body)
return &Message{Body: "Hello From the server"}, nil
}
/gRPC_chat
にサーバーの処理を作成
package main
import (
"grpc-go-chat/chat"
"google.golang.org/grpc"
"log"
"net"
)
func main() {
lis, err := net.Listen("tcp", ":9000")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := chat.Server{}
grpcServer := grpc.NewServer()
chat.RegisterChatServiceServer(grpcServer, &s)
if err := grpcServer.Serve(lis); err != nil {
log.Fatalf("failed to serve: %s", err)
}
}
パッケージのインストール
go mod tidy
クライアントの作成
/gRPC_chat/chat
にサーバーと通信するためのクライアントを作成します。
package main
import (
"grpc-go-chat/chat"
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"log"
)
func main() {
var conn *grpc.ClientConn
conn, err := grpc.Dial(":9000", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatalf("did not connect: %s", err)
}
defer conn.Close()
c := chat.NewChatServiceClient(conn)
resp, err := c.SayHello(context.Background(), &chat.Message{
Body: "Hello From Client!",
})
if err != nil {
log.Fatalf("Error when calling SyaHello: %s", err)
}
log.Printf("Responce from server: %s", resp.Body)
}
サーバの起動
$ go run server.go
クライアントの実行
もう一つのターミナルで
$ go run client.go
2023/07/05 14:08:31 Responce from server: Hello From the server
2023/07/05 14:08:31 Receive message body from client: Hello From Client!
双方のターミナルでメッセージが受け取られていることが確認できているとわかります。
まとめ
gRPCの実装いかがでしたでしょうか?
手順通りに踏んでいけば実装できる内容にしてみました!
実際にgRPCの学習を自身で体験してみた気づいたことがあります。
やはり学習コストが高いです...
いろいろなサイトに残ってる情報が古かったり、そもそもprotoファイルの記述が難しかったりなどがありました。
しかし、その分双方向ストリーミングの利点などに気づかされました。
これからもすこしづつ触っていきたいと思います。
ご清聴ありがとうございました!!!
以下参照したサイト等です
Discussion