LoginSignup
22
14

More than 3 years have passed since last update.

Golang 初心者向けgRPCを使ってみよう

Last updated at Posted at 2019-04-12

はじめに

「gRPCって何?」
「gRPCを聞いたことあるけど使ったことがない。」
「gRPCをGolang/Go言語で使うにはどうしたらいいの?」

という人向け(私です)に記載しました。
gRPCをGolangで使ってみましょう。

「Go Quick Start」 を参考にしています。
https://grpc.io/docs/quickstart/go.html

gRPCとは

gRPC は、Googleが開発したプロトコルです。デフォルトでは、Protocol Bufferを使って、データをシリアライズ化し、高速な通信が可能です。

gRPCでは、クライアントアプリケーションは別のマシン上のサーバーアプリケーションのメソッドをローカルオブジェクトのように直接呼び出すことができるため、分散型のアプリケーションやサービスを簡単に作成できます。

gRPCは多くの言語をサポートしています。たとえば、Go、Python、またはRubyのクライアントを使用して、JavaでgRPCサーバーを簡単に作成できます。

image.png

Golangで開発してみる

Goのバージョン

gRPCは、Goのバージョンが1.6以上で使えます。下記のコマンドでバージョンを確認してください。

$ go version

gRPCのインストール

下記のコマンドでgRPCをインストールします。

$ go get -u -v google.golang.org/grpc

Protocol Buffers v3のインストール

自分の環境に合わせて、こちらからダウンロードします。
https://github.com/protocolbuffers/protobuf/releases

PATHの通ったディレクトリに解凍したディレクトリの/bin の中のバイナリを移してください。

また、macの場合は、下記のコマンドでもインストールできます。

$ brew install protobuf

次に、Golang用の protoc pluginを下記のようにインストールします。

$ go get -u github.com/golang/protobuf/protoc-gen-go

もしGolangのPathを通してない場合は、下記のようにPathを通しましょう。

$ export PATH=$PATH:$GOPATH/bin

サンプルのビルド

サンプルディレクトリへ移動します。

$ cd $GOPATH/src/google.golang.org/grpc/examples/helloworld

gRPCでは、.protoファイルを作成します。
protocコンパイラを使って、.protoファイルをビルドして、.pb.goファイルを作成します。
(※サンプルではすでにhelloworld.pb.goが作成されています。)

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

HelloWorldの実行

サーバとクライアントを実行して、HelloWorldを実行してみましょう。

$ go run greeter_server/main.go

別のターミナルを開いて、下記を実行します。

$ go run greeter_client/main.go

すると、Greeting: Hello worldと表示されます。
gRPCを使って、client-serverアプリケーションを実行できました。

gRPCの更新

gRPCを更新してみます。helloworld.procを下記のように更新します。
SayHelloAgainを追加しています。

helloworld.proc
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";

package helloworld;

// 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コンパイラを使って、.protoファイルをビルドして、.pb.goファイルを作成します。

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

次に、greeter_server/main.goのファイルを更新します。

func (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    return &pb.HelloReply{Message: "Hello again " + in.Name}, nil
}

を追加して、下記のようになります。

greeter_server/main.go
/*
 *
 * Copyright 2015 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

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

// Package main implements a server for Greeter service.
package main

import (
    "context"
    "log"
    "net"

    "google.golang.org/grpc"
    pb "google.golang.org/grpc/examples/helloworld/helloworld"
)

const (
    port = ":50051"
)

// server is used to implement helloworld.GreeterServer.
type server struct{}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    log.Printf("Received: %v", in.Name)
    return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}

func (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    return &pb.HelloReply{Message: "Hello again " + in.Name}, nil
}

func main() {
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterGreeterServer(s, &server{})
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

次に、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.Message)

を追加して、下記のようになります。

greeter_client/main.go
/*
 *
 * Copyright 2015 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// Package main implements a client for Greeter service.
package main

import (
    "context"
    "log"
    "os"
    "time"

    "google.golang.org/grpc"
    pb "google.golang.org/grpc/examples/helloworld/helloworld"
)

const (
    address     = "localhost:50051"
    defaultName = "world"
)

func main() {
    // Set up a connection to the server.
    conn, err := grpc.Dial(address, grpc.WithInsecure())
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()
    c := pb.NewGreeterClient(conn)

    // Contact the server and print out its response.
    name := defaultName
    if len(os.Args) > 1 {
        name = os.Args[1]
    }
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()
    r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }
    log.Printf("Greeting: %s", r.Message)
    r, err = c.SayHelloAgain(ctx, &pb.HelloRequest{Name: name})
    if err != nil {
            log.Fatalf("could not greet: %v", err)
    }
    log.Printf("Greeting: %s", r.Message)
}

上記と同様に、サーバとクライアントを実行して、HelloWorldを実行してみましょう。

$ go run greeter_server/main.go

別のターミナルを開いて、下記を実行します。

$ go run greeter_client/main.go

すると、
Greeting: Hello world
Greeting: Hello again world
と表示されます。

gRPCを使って、client-serverアプリケーションを更新できました。

終わりに

gRPCをGolangで動作してみました。

gRPCを使うと、Rest APIは使えなくなるのですが、gRPC-gatewayを使うと使用することができます。
それはまた別途記載します。

記載しました。
https://qiita.com/ryu3/items/b2882d4f45c7f8485030

22
14
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
14