gRPC(三)基礎:gRPC快速入門

lin鍾一發表於2022-11-09

個人網站:linzyblog.netlify.app/
示例程式碼已經上傳到github:點選跳轉
gRPC官方文件:點選跳轉

1、什麼是gRPC?

gRPC 是一個強大的開源 RPC(遠端過程呼叫)框架,用於構建可擴充套件且快速的 API。它允許客戶端和伺服器應用程式透明地通訊並開發連線的系統。gRPC框架依賴 HTTP/2、協議緩衝區和其他現代技術堆疊來確保最大的 API 安全性、效能和可擴充套件性。

在 gRPC 中,客戶端應用程式可以直接呼叫不同機器上的伺服器應用程式上的方法,就像是本地物件一樣,更容易建立分散式應用程式和服務

與許多 RPC 系統一樣,gRPC 基於定義服務的思想,指定可以遠端呼叫的方法及其引數和返回型別。在服務端,服務端實現這個介面並執行一個 gRPC 伺服器來處理客戶端呼叫。在客戶端,客戶端有一個存根(自動生成的檔案),它提供與伺服器相同的方法。

在這裡插入圖片描述

2、gRPC 的歷史

2015 年,Google 開發了 gRPC 作為 RPC 框架的擴充套件,以連結使用不同技術建立的許多微服務。最初,它與 Google 的內部基礎設施密切相關,但後來,它被開源並標準化以供社群使用。在其釋出的第一年,頂級組織利用它來支援從微服務到 Web、移動和物聯網的用例。並在 2017 年因越來越受歡迎而成為雲原生計算基金會(CNCF)孵化專案。

3、使用Protobuf

Protobuf 是 Google 的序列化/反序列化協議,可以輕鬆定義服務和自動生成客戶端庫。gRPC 使用此協議作為其介面定義語言 (IDL) 和序列化工具集。

  • 客戶端和伺服器之間的 gRPC 服務和訊息在 proto 檔案中定義。
  • Protobuf 編譯器 protoc 生成客戶端和伺服器程式碼,在執行時將 .proto 檔案載入到記憶體中,並使用記憶體中的模式來序列化/反序列化二進位制訊息
  • 程式碼生成後,每條訊息都會在客戶端和遠端服務之間進行交換。

為什麼使用Protobuf?
使用 Protobuf 進行解析需要更少的 CPU 資源,因為資料被轉換為二進位制格式,並且編碼的訊息的大小更輕。因此,訊息交換速度更快,即使在 CPU 速度較慢的機器(例如移動裝置)中也是如此。

4、gRPC架構

在下面的 gRPC 架構圖中,我們有 gRPC 客戶端和伺服器端。在 gRPC 中,每個客戶端服務都包含一個存根(自動生成的檔案),類似於包含當前遠端過程的介面。

gRPC工作流程:

  • gRPC 客戶端將要傳送到伺服器的引數對存根進行本地過程呼叫。
  • 客戶端存根使用 Protobuf 使用編組過程式列化引數,並將請求轉發到本地機器中的本地客戶端時間庫。
  • 作業系統透過 HTTP/2 協議呼叫遠端伺服器機器。
  • 伺服器的作業系統接收資料包並呼叫伺服器存根程式,該程式對接收到的引數進行解碼並使用 Protobuf 執行相應的程式呼叫。
  • 伺服器存根將編碼響應傳送回客戶端傳輸層。客戶端存根取回結果訊息並解包返回的引數,然後執行返回給呼叫者。
    在這裡插入圖片描述

使用 Go 來編寫 gRPC Server 和 Client,讓其互相通訊。在此之上會使用到如下庫:

下面示例是在 windows環境中安裝。

google.golang.org/grpc
google.golang.org/protobuf/cmd/protoc-gen-go
google.golang.org/grpc/cmd/protoc-gen-go-grpc
  1. 初始化專案go mod init 專案名稱模組管理依賴項
go mod init go-grpc-examle
  1. 安裝protoc:
➜ go get -u google.golang.org/grpc

透過--version命令檢視是否安裝成功:

➜ protoc --version
libprotoc 3.20.1
  1. 使用以下命令為 Go 安裝協議編譯器外掛:
➜ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
➜ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2

驗證外掛是否安裝成功:

➜ protoc-gen-go --version
protoc-gen-go.exe v1.28.1

➜ protoc-gen-go-grpc --version
protoc-gen-go-grpc 1.2.0
  1. 更新你的PATH,以便protoc編譯器可以找到外掛(你不在gopath下建立的專案,這裡自行百度改一下PATH)

1、目錄結構

go-grpc-example
├── client
│   └──hello_client
│       └── client.go
├── proto
│   └──hello
│       └── hello.proto
├── server
│   └──hello_server
│       └── server.go

2、編寫 .proto 檔案

syntax = "proto3";

// 定義go生成後的包名
option go_package = "./;hello";
package proto;

// 定義入參
message Request {
  string name =1;
}
// 定義返回
message Response {
  string result = 1;
}

// 定義介面
service UserService {
  rpc Say(Request) returns (Response);
}

3、生成Go程式碼

# 同時生成hello.pb.go 和 hello_grpc.pb.go
➜ protoc --go-grpc_out=. --go_out=. hello.proto

當前目錄下可以看到生成兩個檔案:
在這裡插入圖片描述

4、編寫 Server 服務端程式碼

編寫 gRPC Server 的基礎模板,完成一個方法的呼叫。對 server.go 寫入如下內容:

type HelloService struct {
    // 必須嵌入UnimplementedUserServiceServer
    hello.UnimplementedUserServiceServer
}

// 實現SayHi方法
func (h *HelloService) SayHi(ctx context.Context, req *hello.Request) (res *hello.Response, err error) {
    format := time.Now().Format("2006-01-02 15:04:05")
    return &hello.Response{Result: "hi " + req.GetName() + "---" + format}, nil
}

const PORT = "8888"

func main() {
    // 建立grpc服務
    server := grpc.NewServer()
    // 註冊服務
    hello.RegisterUserServiceServer(server, &HelloService{})

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

    server.Serve(lis)
}

5、編寫 Client 客戶端程式碼

接下來編寫 gRPC Go Client 的基礎模板,開啟 hello_client/client.go 檔案,寫入以下內容:

const PORT = "8888"

func main() {
    // 建立連結
    conn, err := grpc.Dial(":"+PORT, grpc.WithInsecure())
    if err != nil {
        log.Fatalf("grpc.Dial err: %v", err)
    }
    // 一定要記得關閉連結
    defer conn.Close()

    // 例項化客戶端
    client := hello.NewUserServiceClient(conn)
    // 發起請求
    response, err := client.SayHi(context.Background(), &hello.Request{Name: "lin鍾一"})
    if err != nil {
        log.Fatalf("client.SayHi err: %v", err)
    }
    fmt.Printf("resp: %s", response.GetResult())
}

6、啟動 & 請求

# 啟動服務端
$ go run server.go
API server listening at: 127.0.0.1:50970

# 啟動客戶端
$ go run client.go 
API server listening at: 127.0.0.1:51040
resp: hi lin鍾一---2022-11-01 14:54:01

在本文,我們對 gRPC Client/Server 進行了介紹和了解。希望你結合第一章寫的rpc請求的方法對文中講述內容再寫一個 Demo 進行深入瞭解。

下一篇關於gRPC Streaming的內容,gRPC 三種型別的流式。

  • Server-side streaming RPC:伺服器端流式 RPC
  • Client-side streaming RPC:客戶端流式 RPC
  • Bidirectional streaming RPC:雙向流式 RPC
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章