趣談談網路協議---跨語言類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 標識後面的資料型別。
在靈活性方面,這種基於協議檔案的二進位制壓縮協議存在更新不便的問題。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 代理,完全將服務治理抽象到平臺層解決。