My External Storage

Jan 1, 2018 - 5 minute read - Comments - Go gRPC

[Go]gRPCのGo Quick Startをやってみた。

gRPCについて理解を始めるため、gRPCのクイックスタートをやったのでメモしておく。

Go Quick Start
https://grpc.io/docs/quickstart/go.html

ちなみに今回行ったのは、Goのクイックスタートだが、公式には以下の言語のクイックスタートが用意されている。

  • C++
  • Java
  • Python
  • Go
  • Ruby
  • Node.js
  • C#
  • Objective-C
  • Android Java
  • PHP

TL;DR

  • google.golang.org/grpcリポジトリを取得すればサンプルコードもついてくる
  • サンプルの内容は以下
    • 定義済みのプロトコルバッファーを呼ぶコードを動かす
    • プロトコルバッファーに定義を追加して再コンパイルしたAPIを実行する
  • reflection.Registerしているところはとりあえず無視してよいみたい
  • Server Reflectionとはなんなのか?別途調べる。

What is gRPC?

What is gRPC?
https://grpc.io/docs/guides/index.html

翻訳された方がいらっしゃった。

gRPCとは何か?
http://hapoon.hateblo.jp/entry/2017/09/28/171123

「なぜ必要なのか?」はこの辺を読むとよさそう。

第24回 マイクロサービス・システムにおけるgRPCの役割(前編)
https://www.school.ctc-g.co.jp/columns/nakai2/nakai224.html

gRPCを利用するための準備。

Macの場合、protobufbrew経由でインストールできる。

$ go get -u google.golang.org/grpc
$ brew install protobuf
$ go get -u github.com/golang/protobuf/protoc-gen-go

GOPATHPATHを通していない場合は、$ export PATH=$PATH:$GOPATH/binもしておく。

google.golang.org/grpcの中にサンプルコードがあるのでカレントディレクトリを移動する。サンプルコードの構成は以下。

.
├── greeter_client
│   └── main.go
├── greeter_server
│   └── main.go
├── helloworld
│   ├── helloworld.pb.go
│   └── helloworld.proto
└── mock_helloworld
    ├── hw_mock.go
    └── hw_mock_test.go

helloworld.protoファイルにプロトコルバッファーと呼ばれるgRPCでやりとりするデータが定義されている。.protoファイルをプロトコルコンパイラー(protc)でコンパイルすることで各言語用のgRPCコードを自動生成できる。サンプルコードではすでにコンパイル済みのhelloworld.pb.goファイルが同梱されている。

プロトコルバッファーの定義についてもっと知りたいときは以下を参照することで確認できる。

What is gRPC?
https://grpc.io/docs/#what-is-grpc

gRPC Basics: Go.
https://grpc.io/docs/tutorials/basic/go.html

サーバ側を起動しておいてクライアントコードを実行すると、レスポンスが受け取れることを確認できる。

$ go run greeter_server/main.go

-----------------

$ go run greeter_client/main.go
2017/12/31 14:11:52 Greeting: Hello world

プロトコルバッファーの更新

.protoファイルに新しいプロトコルをひとつ追加する。

diff --git a/examples/helloworld/helloworld/helloworld.proto b/examples/helloworld/helloworld/helloworld.proto
index d79a6a0..becd915 100644
--- a/examples/helloworld/helloworld/helloworld.proto
+++ b/examples/helloworld/helloworld/helloworld.proto
@@ -24,6 +24,8 @@ package helloworld;
 service Greeter {
   // Sends a greeting
   rpc SayHello (HelloRequest) returns (HelloReply) {}
+  // Sends another greeting
+  rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
 }

 // The request message containing the user's name.

その後、protocコマンドで再コンパイルをする。

$ protoc -I helloworld/ helloworld/helloworld.proto --go_out=plugins=grpc:helloworld

そうすると、.pb.goファイルが更新され、新しいコードが自動生成される。

        SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error)
+       // Sends another greeting
+       SayHelloAgain(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error)
 }

 type greeterClient struct {
@@ -104,11 +106,22 @@ func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...
        return out, nil
 }

+func (c *greeterClient) SayHelloAgain(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) {
+       out := new(HelloReply)
+       err := grpc.Invoke(ctx, "/helloworld.Greeter/SayHelloAgain", in, out, c.cc, opts...)
+       if err != nil {
+               return nil, err
+       }
+       return out, nil
+}
+
 // Server API for Greeter service
...

greeter_server/main.gogreeter_client/main.goにチュートリアル通りの実装を追加して、実行すると、追加した定義を使った通信ができた。

$ go run greeter_client/main.go
2017/12/31 16:35:46 Greeting: Hello world
2017/12/31 16:35:46 Greeting: Hello again world

サンプルコードの実装

動作確認だけではなく、実装についても確認した。

サーバ側の実装

https://github.com/grpc/grpc-go/blob/master/examples/helloworld/greeter_server/main.go

サーバ側の実装は以下のことをしている。

  • GreeterSeverインタフェースを実装した構造体を定義する
  • net.ListenでTCPプロトコルのリスナーを生成する
  • grpc.NewSeverメソッドでgrpc.Serverオブジェクトを手に入れる
  • プロトコルバッファーから自動生成したRegisterGreeterServerメソッドで構造体をgrpc.Serverに登録する
  • Serveで接続の待機を解する。

途中のreflection.Registerメソッドを使っているのだが、これはServer Reflectionとやらを行うためのものらしいので、今回は触れない。(このHello WorldサンプルがServer Reflectionのチュートリアルも兼ねているからコールされているらしい)

Server Reflectionについては別途調べる。

クライアント側の実装

https://github.com/grpc/grpc-go/blob/master/examples/helloworld/greeter_client/main.go

クライアント側は通常のAPIクライアントとあまり変わり無さそうな感じの実装。コネクションがgrpc.ClientConnオブジェクトなのが大きな違い。

  • grpc.Dialメソッドでコネクションを生成する
  • NewGreeterClientでクライアントの実装を得る。
  • ContextとRequest用の構造体を渡し、クライアントのメソッドをコールする

クイックスタートを終えて

さっと用意して、プロトコルバッファーを自分でコンパイルして利用するところまで出来てよかった。次はBasic Tutorialwをやってみてもう少し具体的にgRPCについて理解する。

gRPC Basics: Go.
https://grpc.io/docs/tutorials/basic/go.html

また、Server reflectionがわからないままなので調べる。この辺を読めば良いらしい?

GRPC Server Reflection Protocol
https://github.com/grpc/grpc/blob/master/doc/server-reflection.md

package reflection
https://godoc.org/google.golang.org/grpc/reflection

gRPC Server Reflection Tutorial
https://github.com/grpc/grpc-go/blob/master/Documentation/server-reflection-tutorial.md

参考URL

What is gRPC?
https://grpc.io/docs/guides/index.html

gRPCとは何か?
http://hapoon.hateblo.jp/entry/2017/09/28/171123

第24回 マイクロサービス・システムにおけるgRPCの役割(前編)
https://www.school.ctc-g.co.jp/columns/nakai2/nakai224.html

Why do we need to register reflection service on gRPC server
https://stackoverflow.com/questions/41424630/why-do-we-need-to-register-reflection-service-on-grpc-server

gRPC Basics - Go
https://grpc.io/docs/tutorials/basic/go.html

GRPC Server Reflection Protocol
https://github.com/grpc/grpc/blob/master/doc/server-reflection.md

package reflection
https://godoc.org/google.golang.org/grpc/reflection

gRPC Server Reflection Tutorial
https://github.com/grpc/grpc-go/blob/master/Documentation/server-reflection-tutorial.md

gRPC関連の記事

Tags: golang grpc

2017年振り返り [書評]SOFT SKILLSを読んだ

comments powered by Disqus