GO言語での gRPC 環境構築
Go言語がインストールされいてる前提です。go
コマンドが使えればOKです。
gRPCのインストール
Go言語での gRPC をインストールします。
$ go get -u google.golang.org/grpc
protocのダウンロード
.proto ファイルをコンパイルする protoc
コマンドを使えるようにコンパイラをインストールします。
Releases · protocolbuffers/protobuf
上記URLからOS環境に合わせてダウンロードしてください。Windows OS(64bit)の場合、例えば protoc-3.8.0-rc-1-win64.zip
です。バージョンは適宜最新版を落とします。
ダウンロードしたZIPファイルを解凍してできたディレクトリ直下にある /bin
にパスを通します。
protocのGo用のプラグインをインストール
Goのコードを生成するためのプラグイン(protoc-gen-go
)をインストールします。
$ go get -u github.com/golang/protobuf/protoc-gen-go
これで準備完了です。
実装
実装に移ります。
gRPC の通信パターン
gRPC による通信はいくつかのパターンに分かれます。
- Simple-RPC
- ServerSideStreaming-RPC
- ClientSideStreaming-RPC
- BidirectionalStreaming-RPC
今回実装するのは 1 の Smple-RPC です。
Simple-RPC
Simple-RPC は Client からの送信1件に対して、Server から1件の送信があり完了する通信です。
ServerSideStreaming-RPC
ServerSideStreaming-RPC は Client からのリクエスト1件に対して、Server から複数件のレスポンスがあるパターンです。
ClientSideStreaming-RPC
ClientSideStreaming-RPC は ServerSideStreaming-RPC の逆で Client からリクエストが複数件があって、Server から1件のレスポンスで完了する通信です。
BidirectionalStreaming-RPC
BidirectionalStreaming-RPC は 名前の通り双方向(Bidirectional)の通信を実現します。Client も Server も複数件リクエストとレスポンスを送信しあう通信です。
当然ながら複数件のリクエストないしレスポンスを制御するのは大変です。したがって今回は最もシンプルな Simple-RPC です。
ディレクトリ作成
まずは適当な作業ディレクトリに “/pb” “/proto” ディレクトリをそれぞれ作成します。”/proto” は .proto ファイルを配置します。そのコンパイル結果を “/pb” ディレクトリに出力します。
.proto ファイル作成
では .proto ファイルにデータのインターフェースを定義します。
/proto/increment.proto
syntax = "proto3";
package increment;
message IncrementRequest {
int32 number = 1;
}
message IncrementResponse {
int32 number = 1;
}
service IncrementService {
rpc Increment (IncrementRequest)
returns (IncrementResponse);
}
IKncrementRequest
がリクエスト時のデータ型、IncrementResponse
がレスポンス時のデータ型です。それぞれ string 型のデータを1つだけ持ちます。
.pb.go ファイル生成
この .proto ファイルをコンパイルし Go言語に変換します。proto
コマンドを使います。
$ protoc --proto_path ./proto --go_out=plugins=grpc:./pb increment.proto
パラメータ --proto_path
はコンパイル対象の .proto ファイルを検索するディレクトリを指定します。今回は /proto いかに .proto ファイルがあるので指定しています。
パラメータ --go_out
はコンパイルして得られたGoファイルの出力先を指定します。
以上2つのパラメータを指定して increment.proto ファイルをコンパイルしています。コンパイルと /pb/increment.pb.go
が生成されていることが確認できます。このファイルには proto で定義したインターフェースが以下のように出力されています。
- Request
- Response
- Client, Server
- RegisterMethod
.proto ファイルを定義しただけで必要な Go でのインターフェースが出力されるのは便利でです。
service 実装してサーバーを立てる
生成された Go ファイルのインターフェースを使ってサーバー側で呼び出されるサービスを実装します。
Incrementは単純にリクエストで渡された数値をインクリメントした数値を返します。
server/service.go
package main
import (
"context"
pb "../pb"
)
type incrementService struct{}
func (s *incrementService) Increment(ctx context.Context, req *pb.IncrementRequest) (*pb.IncrementResponse, error) {
n := req.GetNumber() + 1
return &pb.IncrementResponse{Number: n}, nil
}
簡単です Increment()
では、リクエストのインターフェースから数値を取り出し1プラスし、それをレスポンスのインターフェースで返します。
次にこのサービスを呼び出すサーバーを実装します。
/server/main.go
package main
import (
"log"
"net"
pb "../pb"
"google.golang.org/grpc"
)
func main() {
listen, err := net.Listen("tcp", "localhost:55555")
if err != nil {
log.Fatalln(err)
}
server := grpc.NewServer()
service := &incrementService{}
pb.RegisterIncrementServiceServer(server, service)
server.Serve(listen)
}
実装内容は以下の通りです。
net.Listen()
で TCPのリスナを作成します。grpc.NewServer()
で gRPCサーバーを作成します。- 生成したコードの
RegisterIncrementServiceServer()
を使ってgRPCサーバーにサービスを登録します。 server.Serve()
でサーバーを起動します。
起動が確認できれば次はこのサーバーに接続するクライアントを作成します。
クライアントの作成
最後にクライアントを実装します。
/client/main.go
package main
import (
"context"
"fmt"
"log"
"time"
pb "../pb"
"google.golang.org/grpc"
)
func main() {
connection, err := grpc.Dial("localhost:55555", grpc.WithInsecure())
if err != nil {
log.Fatalln("did not connect: %s", err)
}
defer connection.Close()
client := pb.NewIncrementServiceClient(connection)
// タイムアウトを1秒に設定する
context, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
// 適当な数を送信してみる
var number int32 = 1000
// 送信処理を呼び出す
response, err := client.Increment(context, &pb.IncrementRequest{Number: number})
if err != nil {
log.Println(err)
}
fmt.Println(response.GetNumber()) // 1001
}
実装内容は以下の通りです。
grpc.Dial()
で Connectionを生成する。この際、デフォルトで TLS が必須なのでオプション(grpc.WithInsecure()
)でこれを回避する。NewIncrementServiceClient()
で コネクションを渡してクライアント生成する。- .proto で定義した Increment() を呼び出して、データを送信する。
- レスポンスから結果を取り出し表示
1度だけ定義した数を送信し、その結果を表示するだけのクライアントプログラムです。例では 1000 を投げて 1001 が返ってきます。そして結果が表示されるはずです。
サーバーを起動して、クライアントを起動すると動きます。
以上。
コメントを書く