gRPCを触ってみる

# はじめに
gRPCのQuickStartをとりあえずトレースしてみたいと思います。

# 環境
* OS
    * Debian 4.9 on GCP
* Lang
    * Go
* バージョンは特に断りなければ2019/09/03時点の最新を入れました。
* 環境変数は適宜profileファイルに書くなどしてもらえればと思います。

# Goのインストール
## インストール
```
wget https://dl.google.com/go/go1.12.9.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.12.9.linux-amd64.tar.gz
export GOPATH=$HOME/go
```

## インストール後の確認
[ここ](https://golang.org/doc/install?download=go1.12.9.linux-amd64.tar.gz#testing)の手順に従って、Go環境が動くことを確認します。

# gRPCのインストール
## 先にgitが必要です。
```
sudo apt update
sudo apt upgrade
sudo apt install git
```

##次にgRPCのインストール
```
go get -u google.golang.org/grpc
```

# Protocol Buffersのインストール
先に`unzip`が無かったので入れました。

```
sudo apt install unzip 
wget https://github.com/protocolbuffers/protobuf/releases/download/v3.9.0-rc1/protoc-3.9.0-
rc-1-linux-x86_64.zip
sudo mkdir /usr/local/protoc
sudo unzip protoc-3.9.0-rc-1-linux-x86_64.zip -d /usr/local/protoc/
go get -u github.com/golang/protobuf/protoc-gen-go
export PATH=$PATH:$GOPATH/bin
```

# サンプルを落として試してみる。
## まずは動くかやってみる。

```
go get google.golang.org/grpc
cd $GOPATH/src/google.golang.org/grpc/examples/helloworld
```
2つターミナル立ち上げて実行する。

```bash:１つめのターミナル
go run greeter_server/main.go
2019/09/03 12:33:08 Received: world <- clientからのrequestが届いたら出る
```

```bash:２つめのターミナル
go run greeter_client/main.go
2019/09/03 13:47:59 Greeting: Hello world <- serverからのresponseが届いたら出る
```

## rpcメソッド一つ追加してみる。
### protoファイルをいじります。
`service Greeter`に`SayHelloAgain`を追加します。

```go:helloworld/helloworld.proto
// The greeting service definition.
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.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}
```

### コード生成します。
```
protoc -I helloworld/ helloworld/helloworld.proto --go_out=plugins=grpc:helloworld
```

`helloworld.pb.go`をgrepすると、きちんと追加したメソッドのコードが生成されてます。

```
cat helloworld/helloworld.pb.go | grep SayHelloAgain

        SayHelloAgain(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error)
func (c *greeterClient) SayHelloAgain(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply,
 error) {
        err := c.cc.Invoke(ctx, "/helloworld.Greeter/SayHelloAgain", in, out, opts...)
        SayHelloAgain(context.Context, *HelloRequest) (*HelloReply, error)
func (*UnimplementedGreeterServer) SayHelloAgain(ctx context.Context, req *HelloRequest) (*HelloReply, error) {
        return nil, status.Errorf(codes.Unimplemented, "method SayHelloAgain not implemented")
func _Greeter_SayHelloAgain_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor 
grpc.UnaryServerInterceptor) (interface{}, error) {
                return srv.(GreeterServer).SayHelloAgain(ctx, in)
                FullMethod: "/helloworld.Greeter/SayHelloAgain",
                return srv.(GreeterServer).SayHelloAgain(ctx, req.(*HelloRequest))
                        MethodName: "SayHelloAgain",
                        Handler:    _Greeter_SayHelloAgain_Handler,
```

### mainにコードを追加します。
```go:greeter_server/main.go
func (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
        return &pb.HelloReply{Message: "Hello again " + in.GetName()}, nil
}
```

```go:greeter_client/main.go
r, err = c.SayHelloAgain(ctx, &pb.HelloRequest{Name: name})
if err != nil {
        log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetMessage())
```

### 動かしてみます。
```bash:１つめのターミナル
go run greeter_server/main.go
2019/09/05 08:15:08 Received: world <- clientからのrequestが届いたら出る
```

```bash:２つめのターミナル
go run greeter_client/main.go
2019/09/05 08:15:08 Greeting: Hello world <- serverからのresponseが届いたら出る
2019/09/05 08:15:08 Greeting: Hello again world <- serverからのresponseが届いたら出る
```
# おわり
さくっとサンプル動かすところまでできました、はやい！


# 参考というかまんま↓のチュートリアルをやりました。
[gRPC Go Quick Start](https://www.grpc.io/docs/quickstart/go/)
[Go Getting Started](https://golang.org/doc/install?download=go1.12.9.linux-amd64.tar.gz)