gRPC初體驗

attitude發表於2021-04-25

gRPC是什麼?

gRPC是一個高效能、開源、通用的RPC框架,面向移動和HTTP/2設計
支援多語言:C++C#、Dart、Go、Java、Node.js、Objective-c、PHP、Python、Ruby
特點:HTTP/2、Protobuf、客戶端、服務的基於同一份IDL、行動網路的良好支援、支援多語言

圖解呼叫過程:

gRPC初體驗

1、客戶端(gRPC Stub)發起發起 RPC 呼叫
2、對請求引數使用 Protobuf 進行物件序列化(IDL)
3、服務端(gRPC Server)接收到請求後,解碼請求體,進行業務邏輯處理並返回
4、對響應結果使用 Protobuf 進行物件序列化(IDL)
5、客戶端接受到服務端響應,解碼請求體,返回響應結果

入門示例

首先需要安裝
gRPC:

go get -u google.golang.org/grpc

Protocol Buffers v3

wget https://github.com/google/protobuf/releases/download/v3.5.1/protobuf-all-3.5.1.zip
unzip protobuf-all-3.5.1.zip
cd protobuf-3.5.1/
./configure
make
make install

驗證安裝是否成功:

protoc --version

Protoc Plugin:

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

首先我們新建 hello.proto

syntax = "proto3";

package proto;
option go_package = "/";

service HelloService {
  rpc Hello(HelloRequest) returns (HelloResponse) {}
}

message HelloRequest {
  string request = 1;
}

message HelloResponse {
  string response = 1;
}

其中 option go_package 是指定go包,不然執行編譯時會報錯:
protoc-gen-go: unable to determine Go import path for "hello.proto"
然後再該檔案目錄下執行:

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

該命令會在目錄下生成 hello.pb.go 檔案
新建 server.go 檔案,並寫入以下內容

package main

import (
    "context"
    "google.golang.org/grpc"
    "log"
    "net"
    "proto"
)

type HelloService struct {}

func (s *HelloService) Hello(ctx context.Context, r *proto.HelloRequest) (*proto.HelloResponse, error) {
    return &pb.HelloResponse{Response: "Hello " + r.GetRequest()}, nil
}

const PORT = "8088"

func main()  {
    server := grpc.NewServer()

    proto.RegisterHelloServiceServer(server, &HelloService{})

    lis, err := net.Listen("tcp", ":"+PORT)
    if err != nil {
        log.Fatalf("net.listen err: %v", err)
    }

    server.Serve(lis)
}

新建client.go檔案,並寫入以下內容:

package main

import (
    "context"
    "google.golang.org/grpc"
    "proto"
    "log"
)

const PORT = "8088"

func main()  {
    conn, err := grpc.Dial(":" + PORT, grpc.WithInsecure())
    if err != nil {
        log.Fatalf("grpc.Dial err: %v", err)
    }
    defer conn.Close()

    client := proto.NewHelloServiceClient(conn)
    resp, err := client.Hello(context.Background(), &proto.HelloRequest{
        Request: "gRPC",
    })
    if err != nil {
        log.Fatalf("client.Search err:%v", err)
    }

    log.Printf("resp: %s", resp.GetResponse())
}

啟動server

go run server.go

啟動client

go run client.go

輸出:

$ go run client.go
2021/04/25 15:07:27 resp: Hello gRPC
本作品採用《CC 協議》,轉載必須註明作者和本文連結
attitudefx