2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

gRPC触ってみた

Last updated at Posted at 2019-05-22

install go lang

$ wget https://storage.googleapis.com/golang/go1.2.5.linux-amd64.tar.gz
$ tar vzfx go1.12.5.linux-amd64.tar.gz
$ sudo mv go /usr/local/
$ export PATH=$PATH:/usr/local/go/bin
$ export GOPATH=$HOME/go
$ go version

test

$ mkdir go/src/hello
$ cd go/src/hello
$ touch hello.go
hello.go
package main

import "fmt"

func main() {
	fmt.Printf("hello, world\n")
}
$ go build
$ go run hello

gRPC

gRPCについて

totorials

hoge.proto

記述 記述ルール 説明
ファイル名 スネークケース メッセージとサービスを定義するファイル
メッセージ名 アッパーキャメルケース サーバーとクライアント間でやりとりするデータ
フィールド名 スネークケース データのフィールド名
サービス名 アッパーキャメルケース サーバーとクライアント間で通信するサービス名を定義する。リクエストとレスポンスのメッセージも記述。

公式ガイド

hoge_client/main.go
プロトコルファイルで定義したサービスやメッセージを使用してクライアントサイドサービスの振舞いを実装する。

記述 記述ルール 説明
サービス名 アッパーキャメルケース 振舞いを記述
メッセージフィールド アッパーキャメルケース データのフィールド名

hoge_server/main.go
プロトコルファイルで定義したサービスやメッセージを使用してサーバーサイドサービスの振舞いを実装する。

記述 記述ルール 説明
サービス名 アッパーキャメルケース 振舞いを記述
メッセージフィールド アッパーキャメルケース データのフィールド名

install gRPC

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

Install Protocol Buffers v3

$ go get -u github.com/golang/protobuf/protoc-gen-go
$ export PATH=$PATH:$GOPATH/bin

examples
公式ドキュメント

Go言語に変換(対応言語のProtocol Buffersへ変換)

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

-bash: protoc: command not foundの場合

$ yum install zip
$ yum install unzip
$ PROTOC_ZIP=protoc-3.7.1-linux-x86_64.zip
$ curl -OL https://github.com/google/protobuf/releases/download/v3.7.1/$PROTOC_ZIP
$ sudo unzip -o $PROTOC_ZIP -d /usr/local bin/protoc
$ rm -f $PROTOC_ZIP

注意
proto、server、clientの順にコードを修正する。

お試し

helloworldを参考にさわってみる。

パッケージの準備
src/
 ├ user/
 │ └ user/
 │   └ user.proto
 ├ user_client/
 │   └ get_user.go
 │   └ create_user.go
 ├ user_server/
 │   └ main.go
 └ mock_user/

protoファイル編集

user/user.proto
syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.user";
option java_outer_classname = "UserProto";

package user;

// User service definition.
service User {
  // send user_id
  rpc GetUser (RequestUserId) returns (UserResponse) {}
  // create user
  rpc CreateUser (CreateUserRequest) returns (UserResponse) {}

}

// The request message containing the user's name.
message RequestUserId {
  string user_id = 1;
}

message CreateUserRequest {
  string name = 1;
  string mail = 2;
  BloodType blood_type = 3;
  int32 age = 4;
}

message UserResponse {
  string id = 1;
  string name = 2;
  string mail = 3;
  BloodType blood_type = 4;
  int32 age = 5;
}

enum BloodType {
  A = 0;
  B = 1;
  O = 2;
  AB = 4;
}

Go言語へコンパイル

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

serverファイル編集

user_server/main.go
//go:generate protoc -I ../users --go_out=plugins=grpc:../user ../user/user.proto

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

import (
        "context"
        "log"
        "net"

        "google.golang.org/grpc"
        pb "../user"
)

const (
        port = ":50051"
)

// server is used to implement Users.UsersServer.
type server struct{}

// GetUser implements User.UserServer
func (s *server) GetUser(ctx context.Context, user *pb.RequestUserId) (*pb.UserResponse, error) {
        log.Printf("Received: %v", user.UserId)
        return &pb.UserResponse{
          Id: user.UserId,
          Name:"Tom",
          Mail:"hoge@fuga.com",
          BloodType:0,
          Age:25}, nil
}

// CreateUser implements User.UserServer
func (s *server) CreateUser(ctx context.Context, m *pb.CreateUserRequest) (*pb.UserResponse, error) {
        return &pb.UserResponse{
          Id: "1",
          Name:m.Name,
          Mail:m.Mail,
          BloodType:m.BloodType,
          Age:m.Age}, nil
}

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


clientファイル編集

user_client/get_user.go
// Package main implements a client for User service.
package main

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

        "google.golang.org/grpc"
        pb "../user"
)

const (
        address     = "localhost:50051"
        defaultUserId = "1"
)

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.NewUserClient(conn)

        // Contact the server and print out its response.
        userId := defaultUserId
        if len(os.Args) > 1 {
                userId = os.Args[1]
        }
        ctx, cancel := context.WithTimeout(context.Background(), time.Second)
        defer cancel()
        r, err := c.GetUser(ctx, &pb.RequestUserId{UserId: userId})
        if err != nil {
                log.Fatalf("get user error: %v", err)
        }
        log.Printf("User Name: %s", r.Name)
}
user_client/create_user.go
// Package main implements a client for User service.
package main

import (
        "context"
        "log"
        "time"
        "flag"

        "google.golang.org/grpc"
        pb "../user"
)

const (
        address     = "localhost:50051"
)

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.NewUserClient(conn)

        ctx, cancel := context.WithTimeout(context.Background(), time.Second)
        defer cancel()

        var (
             cName = flag.String("name", "test", "name")
             cMail = flag.String("mail", "test@example.com", "mail")
             cAge = flag.Int("age", 20, "age")
        )
        flag.Parse()

        r, err := c.CreateUser(ctx, &pb.CreateUserRequest{Name: *cName, Mail: *cMail, BloodType:0, Age:int32(*cAge)})
        if err != nil {
                log.Fatalf("could not create user: %v", err)
        }
        log.Printf("Create User: {Id: %s, Name:%s, Mail:%s, BloodType:%s, Age:%s}", r.Id, r.Name, r.Mail, r.BloodType, r.Age)
}

gRPC server start

# 環境変数の登録してなかった場合は環境変数を設定
$ export PATH=$PATH:/usr/local/go/bin
$ export GOPATH=$HOME/go
$ export PATH=$PATH:$GOPATH/bin

$ go run users_server/main.go

gRPC client通信

# 環境変数の登録してなかった場合は環境変数を設定
$ export PATH=$PATH:/usr/local/go/bin
$ export GOPATH=$HOME/go
$ export PATH=$PATH:$GOPATH/bin

$ go run users_client/get_user.go
2019/05/22 06:10:50 User Name: Tom

$ go run user_client/create_user.go -name Thomas -mail test -age 25
2019/05/22 06:10:04 Create User: {Id: 1, Name:Thomas, Mail:test, BloodType:A, Age:%!s(int32=25)}
2
1
0

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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?