【gRpc】golangでgRpcサーバを立ててみる

今回は以下記事の続きで作成したprotocol buffersによって生成したgolangを使って、実際にgRpcサーバを立ててみようと思います。

【gRpc】Protocol Buffersを使ってgolangソースを生成する

上の記事ではでていたWARNINGを別の記事に書いた方法で解消したので正確には以下記事の続きです。

【gRpc】Protocol Buffersを使ってgolangソースを生成する際のWARNINGを解消

環境情報

OS: Windows10 64bit
golang: v1.15.3
Protocol Buffers: v3.13.0

環境変数「APPS=/c/dev」を設定しています。(アプリの配置先)

※コマンドの実行は基本的にgit bashで行っているのでlinuxコマンドになっています。

サンプルコードのリポジトリ

今回使用したサンプルは以下のリポジトリに配置しています。

https://github.com/i-shinya/grpc-client-server-sample

今回までのサンプルコードは以下のコミットで確認できます。

今回までのコード

golangでgRpcサーバを立ててみる

gRpcサーバ用のディレクトリの準備

gRpcサーバ用にディレクトリを用意したいと思います。とりあえずmainを実装するファイルを配置するので以下のようにディレクトリを作成しました。(現在デファクトとなっている構成を元にしています)

.
|-- go-server
|   |-- cmd ・・・ (New) 起動コマンドを配置するディレクトリ
|   `-- internal ・・・ (New) 複数のアプリ実装を束ねるディレクトリ
|       `-- apps ・・・ (New) 今回のサンプルアプリのロジックを実装するディレクトリ
`-- tools
    `-- grpc

gRpc Serviceのinterfaceの生成先を変更する

さっそくgRpcサーバを実装したいところですが、先にProtocol Buffersの生成ファイルの配置先を変更したいと思います。前回は以下のコマンドで生成したのでprotoファイルと同一のディレクトリのgrpc-client-server-sample/tools/grpc内の/adapter/gen_grpcに生成されていました。

cd $APPS/grpc-client-server-sample/tools/grpc

protoc/bin/protoc --go_out=plugins=grpc:./ protos/*.proto

 

golangのファイルがtoolsディレクトリに存在するのは気持ち悪いので、今回新たに追加したディレクトリに配置するようにしたいと思います。

.
|-- go-server
    |-- cmd
    `-- internal
        `-- apps ・・・ ここを生成先に指定する
            `-- adapter
                `-- gen_grpc ・・・ ここに生成される

 

配置先のディレクトリを変更するために実行コマンドを以下のように変更します。

cd $APPS/grpc-client-server-sample/tools/grpc

protoc/bin/protoc --go_out=plugins=grpc:../../go-server/internal/apps/ protos/*.proto

これで配置先が変わったはずです。

go modulesを導入する

golangのパッケージ管理として公式から提供されているgo modulesを導入します。導入は以下のコマンドを実行するのみでOKです。

cd $APPS/grpc-client-server-sample/go-server

// go-serverはモジュール名なので任意で変更してください。
go mod init go-server

こちらを実行するとgo.modファイルが作成されるはずです。これで導入完了です。

gRpc用のパッケージをgo getする

gRpcサーバを立てるためのライブラリはgoogleが提供しているgrpc-goを使用します。go.modが配置されているディレクトリで以下を実行すればインストールできます。

go get -u google.golang.org/grpc

Protocol Buffersで生成したServiceの実装を追加

生成したコードはあくまでinterfaceなので実際に使用する際はinterfaceの実装を追加する必要があります。今回は生成されたsample.pb.goの実装をadapterパッケージ配下にimplディレクトリを作成し、こちらにsample_adapter.goを作成し以下のような実装をいれました。(すごく適当です。)

package impl

import (
	"context"
	pb "go-server/internal/apps/adapter/gen_grpc"
)

type SampleAdapter struct {}

func (s *SampleAdapter) GetMySample(ctx context.Context, message *pb.Sample_GetMySampleMessage) (*pb.Sample_MySampleResponse, error) {
	return &pb.Sample_MySampleResponse{
		Name: "hogehoge",
		Kind: "fugafuga",
	}, nil
}

これで実装はOKです!!

gRpcサーバを起動するmainを追加する

ようやく準備が終わりました!それではgRpc起動用のmainを追加します。配置先はgo-server/cmd内でgrpc_main.goというファイル名にしました。

最初はサーバを起動するだけのコードで以下のように書きました。(gRpcのServiceは呼び出せない)

package main

import (
	"google.golang.org/grpc"
	"log"
	"net"
)

func main() {
	log.Println("Starting main.")
	s := grpc.NewServer()

	listener, err := net.Listen("tcp", ":5555")
	if err != nil {
		log.Fatalln(err)
	}
	log.Println("Server starting.")
	err = s.Serve(listener)
	if err != nil {
		log.Fatalln(err)
	}
}

以下のコマンドを実行すればポート5555でサーバが起動します。

cd $APPS/grpc-client-server-sample/go-server

go run cmd/grpc_main.go

ただし、これでは何も実行できないので、gRpcのServiceを使えるようにします。

gRpcのServiceを登録してサーバを実行する

生成したgRpcコードには登録用のメソッドRegisterSampleAdapterServer()が定義されているので、こちらに実装用のStructを渡して登録します。

package main

import (
	"go-server/internal/apps/adapter"
	pb "go-server/internal/apps/adapter/gen_grpc"
	"google.golang.org/grpc"
	"log"
	"net"
)

func main() {
	log.Println("Starting main.")
	s := grpc.NewServer()

	// gRpcのメソッドを登録する
	registerGrpcAdapter(s)

	listener, err := net.Listen("tcp", ":5555")
	if err != nil {
		log.Fatalln(err)
	}
	log.Println("Server starting.")
	err = s.Serve(listener)
	if err != nil {
		log.Fatalln(err)
	}
}

// gRpcで生成したadapterを登録する
// gRpc Serviceを追加した場合はここに記載を追加していく
func registerGrpcAdapter(s *grpc.Server) {
	// SampleAdapterを登録する
	pb.RegisterSampleAdapterServer(s, &adapter.SampleAdapter{})
}

これでサンプルとして実装した処理を行えます。早速以下の記事で紹介したgRpc用のテストクライアント「Bloom RPC」を使用して動作確認してみます。

【gRpc】シンプルなgRpc用のテストクライアントツール「BloomRPC」の紹介

動作確認する

再びサーバを起動した状態でBloom RPCを起動し、Sample.protoを読み込んで実行してみます。

ちゃんとhogehogeとfugafugaが返ってきました!(適当すぎる・・・)

 

今回はこれにて終了です。記事書くの疲れた・・・。

参考

https://qiita.com/marnie_ms4/items/4582a1a0db363fe246f3

https://qiita.com/kwashi/items/533bbb7d09e723c8b56f

https://qiita.com/ryu3/items/d5cc28a412a06e17ef98