1. 程式人生 > >趣談談網路協議---跨語言類RPC協議:交流之前,雙方先來個專業術語表

趣談談網路協議---跨語言類RPC協議:交流之前,雙方先來個專業術語表

GRPC 是一種二進位制,效能好,跨語言,還靈活,同時可以進行服務治理的多快好省的 RPC 框架,唯一的不足是要寫協議檔案。

GRPC 序列化使用 Protocol Buffers,網路傳輸使用 HTTP 2.0,服務治理可以使用基於 Envoy 的 Service Mesh。

Protocol Buffers

GRPC 要同時做到使用二進位制、跨語言,需要雙方定義一個協議檔案 .proto,規定好雙方溝通的專業術語。

以購買專欄為例:

syntax = “proto3”;    # 使用 proto3 語法
package com.geektime.grpc
option java_package = “com.geektime.grpc”;
message Order {            # 訊息型別,發出去的引數
  required string date = 1;    #   欄位都有唯一的標識,壓縮時只需傳輸數字標識即可
  required string classname = 2;
  required string author = 3;
  required int price = 4;
}

message OrderResponse {          # 訊息型別,返回的結果
  required string message = 1;
}

service PurchaseOrder {    # 定義 Service
  rpc Purchase (Order) returns (OrderResponse) {}  #  RPC 呼叫
}

型別中的欄位都有唯一的標識,壓縮時只需傳輸數字標識即可。

無論使用什麼語言,都有相應的工具生成客戶端和服務端的 Stub 程式,這樣客戶端就可以像呼叫本地一樣呼叫遠端服務。

協議約定問題

Protocol Buffers 是一款壓縮率極高的序列化協議。對於 int 型別,Protocol Buffers 使用變長整數形式。

每一個 Byte 的 8 位,最高位都有特殊的含義:

  • 為 1,表示後續的 Byte 也屬於該數。
  • 為 0,該數到此結束。

每個欄位,使用 TLV(Tag, Length, Value)儲存方式。其中,Tag = (field_num << 3) | wire_type。field_num 是在 proto 檔案中國,給每個欄位指定的唯一數字標識,wire_type 標識後面的資料型別。 在這裡插入圖片描述

例如,對於 string author = 3,field_num 為 3,string 的 wire_type 為 2,有 11 << 3 | 10 = 11000 | 10 = 11010 = 26;Value 為 “liuchao”,如果使用 UTF-8 編碼,長度為 7 個字元。所以,最終儲存形式為(26, 7, liuchao)。在序列化效率方面做到了極致。

在靈活性方面,這種基於協議檔案的二進位制壓縮協議存在更新不便的問題。Protocol Buffers 考慮了相容性。協議檔案中的每一個欄位都有修飾符,如:

  • required:該值不能為空。
  • optional:可選欄位,不設定時使用預設值。
  • repeated:可重複 0 到多次。

網路傳輸問題

如果時 Java 技術棧,GRPC 的客戶端和伺服器之間通過 Netty Channel 作為資料通道,每個請求被封裝稱 HTTP 2.0 的 Stream。

Netty 是一個高效的基於非同步 IO 的網路傳輸框架。

HTTP 2.0 的傳輸: 在這裡插入圖片描述

由於基於 HTTP 2.0,GRPC 和 其他 RPC 不同,可定義四種服務方法。

1、最常用的單向 RPC,客戶端像服務端傳送一個請求,並獲取一個應答,就像一次普通函式的呼叫。

rpc SayHello(HelloRequest) returns (HelloResponse){}

2、服務端流式 RPC,服務端返回一批結果。

rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){}

3、客戶端流式 RPC,客戶端發出一批請求。

rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {}

4、雙向流式 RPC,兩邊分別通過一個讀寫資料流來發送一系列訊息。

rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){}

基於 HTTP 2.0,客戶端和服務端之間的互動方式比較豐富,不僅可以單向遠端呼叫,還可實現當服務端狀態改變時,主動通知客戶端。

服務發現和治理問題

GRPC 本身沒有提供服務發現機制,需藉助 Envoy,不僅時負載均衡器,還是高效能的 C++ 寫的 Proxy 轉發器,可以配置非常靈活的轉發規則。

規則可以是靜態的,放在配置檔案中,啟動時載入。Envoy 支援熱載入和熱重啟。

最好將規則設定為動態的,放在統一的地方維護,這個統一的地方是服務發現(Discovery Service)。

配置中往往配置 4 項:

  • listener,監聽埠。
  • endpoint,目標 IP 和埠。
  • cluster,是具有完全相同行為的多個 endpoint。從 cluster 到 endpoint 的過程為負載均衡。
  • route,有時多個 cluster 有類似的功能,但版本號不同,可通過 route 規則將請求路由到某一版本號,即某個 cluster。

服務中心需要實現 Envoy 的 API,Envoy 可主動去服務發現中心拉取轉發策略。Envoy 在控制面和服務發現中心溝通時,使用 GRPC。

Envoy 配置規則:

  • 配置路由策略。例如後端服務有 2 個版本,可通過配置 Envoy 的 route,設定兩個版本間,即 兩個 cluster 間的 route 規則,一個佔 99% 的流量,另一個佔 1%。
  • 負載均衡策略。對於一個 cluster 下的多個 endpoint,可配置負載均衡機制和健康檢查機制。 在這裡插入圖片描述 節點的變化均會上傳到註冊中心,策略都可通過註冊中心下發,所以,註冊中心可稱為註冊管理中心。

未來服務治理的趨勢 Service Mesh,應用之間的相互呼叫、服務之間的治理完全由 Envoy 代理,完全將服務治理抽象到平臺層解決。

在這裡插入圖片描述