パパエンジニアのポエム

奥さんと娘ちゃんへの愛が止まらない

GolangでgRPC使ってみた

ほとんど公式のQuickStartのまんまだけど、一応備忘録

gRPCとは

https://grpc.io/img/landing-2.svg

gRPC は、Protocol Buffers を使ってデータをシリアライズし、高速な通信を実現できるRPCフレームワークGoogle謹製)。

セットアップ

  • Install gRPC
go get -u google.golang.org/grpc
  • Install protobuf for Mac
brew install protobuf
  • Install protocol buffers lib for Golang
go get -u github.com/golang/protobuf/protoc-gen-go

.protoファイルを実装する

ドキュメントを参考にインターフェースを定義する。

何も考えずにミニマムでメソッドを作ってみた。

syntax = "proto3";

package proto;

service Test {
  rpc Get (Request) returns (Response);
}

message Request {
  string Message = 1;
}

message Response {
  string Message = 1;
}

.protoファイルから.goファイルを生成する

protocコマンドを使って.protoファイルから.goファイルを生成する。

protoc -I proto/ proto/*.proto --go_out=plugins=grpc:proto

goのインターフェースが定義されたtest.pb.goファイルが作成されているはず。

サーバーサイドプログラミング

何も考えずにtest.pb.goファイルに定義されているインターフェースを実装し、

ポート50051でリッスンする。

package main

import (
    "context"
    "net"

    pb "github.com/yuki-toida/grpc-sample/proto"
    "google.golang.org/grpc"
)

func main() {
    listener, err := net.Listen("tcp", ":50051")
    if err != nil {
        panic(err)
    }
    server := grpc.NewServer()
    pb.RegisterTestServer(server, &Server{})
    server.Serve(listener)
}

type Server struct{}

func (s *Server) Get(c context.Context, r *pb.Request) (*pb.Response, error) {
    return &pb.Response{Message: r.Message}, nil
}

クライアントサイドプログラミング

ポート50051でリッスンされているサーバーに接続するクライアントを実装する。

この例では、コマンドラインパラメータを受け取りそのまま標準出力される。

package main

import (
    "context"
    "fmt"
    "os"
    "time"

    pb "github.com/yuki-toida/grpc-sample/proto"
    "google.golang.org/grpc"
)

func main() {
    conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
    if err != nil {
        panic(err)
    }
    defer conn.Close()

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

    message := "Hello"
    if 1 < len(os.Args) {
        message = os.Args[1]
    }

    client := pb.NewTestClient(conn)
    res, err := client.Get(ctx, &pb.Request{Message: message})
    if err != nil {
        panic(err)
    }
    fmt.Println(res)
}

大規模開発におけるDDD時、gRPCのインターフェースをどの層に依存させるか悩みそう。

素直にユーザーインターフェース層かな、そうするとすごく膨れ上がりそうな気配がする。

GitHub - yuki-toida/grpc-sample