iT邦幫忙

1

Golang-gRPC & Protocol Buffers

之前都是使用RESTful API開發
換工作面試幾輪之後發現有蠻多家公司都在使用gRPC
就多學一個技能,順便做個筆記
希望可以幫助到也是初接觸gRPC的你
每個topic的最後會附上參考資料,建議要進去看過一遍

我的開發環境

  • 語言:Go
  • OS:macOS

gRPC是什麼?

全名:gRPC (gRPC Remote Procedure Calls)

是Google發起的一個開源遠端程序呼叫 (Remote procedure call) 系統。該系統基於 HTTP/2 協定傳輸,使用Protocol Buffers 作為介面描述語言。

gRPC 與 RESTful API & JSON 的比較

講幾個gRPC的優點,其他更加詳細的內容可以參照Microsoft Docs有更詳細的說明

  • 文件即是程式結構,程式內不用另外寫object mapping資料

  • 文件透過binary直接轉譯成程式,支援多種語言

  • 資料會經過protobuf編碼,人類無法直接看懂資料,安全性相較於JSON較高(但同時也是缺點,因為人看不懂)

  • 效能透過protobuf序列化後效能較好

  • 參考資料:https://docs.microsoft.com/zh-tw/aspnet/core/grpc/comparison?view=aspnetcore-5.0

Protobuf

proto2 與 proto3的區別

有的人在第一次看到protobuf的時候可能會注意到有proto2 與 proto3
使用上建議proto3
因為支援更多種語言,也有做出許多改進
詳細請見參考資料

安裝步驟

go get github.com/golang/protobuf/protoc-gen-go
  • 在terminal執行echo $PATH,找到系統路徑,把protocprotoc-gen-go丟到系統路徑去
    注意:PATH預設可能會被隱藏資料夾,mac要看到隱藏資料夾按command+shift+.
    https://ithelp.ithome.com.tw/upload/images/20210222/20118878MRPbnUpw9K.png

撰寫protocol文件,並轉譯成程式碼

撰寫protocol文件

詳細規格可以看文件,以下是簡單tutorial.proto範例

//使用proto3
syntax = "proto3";
//定義所屬package
package tutorial;

//定義輸出的路徑,沒有寫會出現提示警告訊息,但是目前都是生成在執行的資料夾下
//option go_package = "./tutorial";

//定義API interface
service Greeter {
  // Sends a greeting
  rpc SayHello (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;
}
}

轉譯成程式碼

轉化為Go程式的command

protoc --go_out=. *.proto
protoc --go_out=plugins=grpc:. *.proto // 用這個比較好,連grpc的service也會跟著轉譯

Read & Write,proto doc在文末有附上

// ProtoExample ...
func ProtoExample() {
	// 你一定很好奇這個struct在哪,在tutorial.pb.go
	p := HelloRequest{
		Name: "Alice",
	}

	// Writing a Message
	bp, err := proto.Marshal(&p)
	if err != nil {
		log.Fatal(err)
	}

	// Reading a Message
	var data HelloRequest
	if err = proto.Unmarshal(bp, &data); err != nil {
		log.Fatal(err)
	}
	log.Println(&data)
}

gRPC Server & Client

下載gRPC package

go get -u google.golang.org/grpc

實作API & Server端

type service struct {
	UnimplementedGreeterServer
}

func (s *service) SayHello(ctx context.Context, in *HelloRequest) (*HelloReply, error) {
	log.Printf("Received: %v", in.GetName())
	return &HelloReply{Message: "Hello, " + in.GetName()}, nil
}

// GRPCServer ...
func GRPCServer() {
	addr := "127.0.0.1:8080"
	lis, err := net.Listen("tcp", addr)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}

	log.Println("Server listening on", addr)
	gRPCServer := grpc.NewServer()
	RegisterGreeterServer(gRPCServer, &service{})
	if err := gRPCServer.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

實作Client端

const (
	address     = "127.0.0.1:8080"
	defaultName = "world"
)

// GPRCClient ...
func GPRCClient() {
	// Set up a connection to the server.
	conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()
	c := 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, &HelloRequest{Name: name})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	log.Printf("Greeting: %s", r.GetMessage())
}

參考資料:

Bloomrpc

這是去google搜尋之後看到鐵人賽的文章使用的GUI測試工具
專門用來對gRPC做使用

使用方法

  • 按+號import proto file
  • 選擇你要測試的message
  • 輸入data
  • 輸入address
  • 按>號輸出之後就能看到結果

bloomrpc github:https://github.com/uw-labs/bloomrpc

總結

參考的資料非常多,細節很多
文件要多看,只能盡量把作法跟參考資料給集中
總結步驟的話可以分成

  • 安裝binary(protoc、protoc-gen-go。有的範例還有安裝protoc-gen-go-grpc,這裡沒有使用)
  • 撰寫.proto(使用proto3撰寫,定義service、message)
  • 使用binary parse to code
  • 實作API、Server、Client

其他相關


尚未有邦友留言

立即登入留言