2018年4月-8月的專案裡面用到了protobuf+gRPC技術,本文對這兩種技術進行了總結,參考來源於網路,具體連結在文中。

protobuf

定義:

是與json,XML功能相似的一種結構化資料格式,是一種google定義的結構化資料格式,用於在網路通訊間的資料序列化和反序列化,以用於網路傳輸。序列化:將資料結構或物件轉換成二進位制串的過程;反序列化:將在序列化過程中所生成的二進位制串轉換成資料結構或者物件的過程。

特點:

相對於其他格式,protobuf解析速度快(即序列化反序列化速度快),佔用空間小,以及相容性好,很適合做資料儲存或網路通訊間的資料傳輸。

原理:

序列化 & 反序列化簡單 & 速度快的原因是:

a。 編碼 / 解碼 方式簡單(只需要簡單的數學運算 = 位移等等,Varint、Zigzag編碼)

b。 採用protobuf自身的框架程式碼和編譯器共同完成

即序列化後的資料量體積小的原因是:

a。 採用了獨特的編碼方式,如Varint、Zigzag編碼方式等等

b。 採用T - L - V 的資料儲存方式:減少了分隔符的使用 & 資料儲存得緊湊

protobuf+RPC技術

Varint

中每個 位元組 的最高位 都有特殊含義:

如果是 1,表示後續的 位元組 也是該數字的一部分

如果是 0,表示這是最後一個位元組,且剩餘 7位 都用來表示數字

為了更好地減少 表示負數時 的位元組數,protobuf在varint編碼上又增加了zigzag編碼方式進行編碼(移位操作)

T-L-V資料儲存方式:

protobuf+RPC技術

T - L - V

儲存方式的優點是

不需要

分隔符

就能 分隔開

欄位

,減少了

分隔符

的使用

各欄位 儲存得非常緊湊,儲存空間利用率非常高

若 欄位沒有被設定欄位值,那麼該欄位在序列化時的資料中是完全不存在的,即不需要編碼

在使用varint編碼後,只需要用T-V來表示,大大節省了空間。

原文連結:Protocol Buffer 序列化原理大揭秘 - 為什麼Protocol Buffer效能這麼好?

總結:protobuf使用varint編碼和T-V表示方式,大大節省序列化後的資料空間,並且編碼方式簡單,序列化速度很快,並且protobuf直接對資料進行處理,與語言平臺無關,可以供任意語言使用。

在專案中,使用基於protobuf的gRPC,接下來介紹一下RPC。

RPC遠端過程呼叫,是一種封裝了各層網路協議,幷包含序列化和反序列化功能的一種通訊框架,基於protobuf的gRPC相當於序列化和反序列化功能是用protobuf實現的。

protobuf+RPC技術

參考連結:https://blog。csdn。net/b1303110335/article/details/79557292

protobuf+RPC技術

protobuf+RPC技術

protobuf+RPC技術

protobuf+RPC技術

Client A的應用層程式碼中,呼叫了Calculator的一個實現類的add方法,希望執行一個加法運算;

這個Calculator實現類,內部並不是直接實現計算器的加減乘除邏輯,而是透過遠端呼叫Service B的RPC介面,來獲取運算結果,因此稱之為

Stub

Stub怎麼和Service B建立遠端通訊呢?這時候就要用到

遠端通訊工具

了,也就是圖中的

Run-time Library

,這個工具將幫你實現遠端通訊的功能,比如Java的

Socket

,就是這樣一個庫,當然,你也可以用基於Http協議的

HttpClient

,或者其他通訊工具類,都可以,

RPC並沒有規定說你要用何種協議進行通訊

Stub透過呼叫通訊工具提供的方法,和Service B建立起了通訊,然後將請求資料發給Service B。需要注意的是,由於底層的網路通訊是基於

二進位制格式

的,因此這裡Stub傳給通訊工具類的資料也必須是二進位制,比如calculator。add(1,2),你必須把引數值1和2放到一個Request物件裡頭(這個Request物件當然不只這些資訊,還包括要呼叫哪個服務的哪個RPC介面等其他資訊),然後

序列化

為二進位制,再傳給通訊工具類,這一點也將在下面的程式碼實現中體現;

二進位制的資料傳到Service B這一邊了,Service B當然也有自己的通訊工具,透過這個通訊工具接收二進位制的請求;

既然資料是二進位制的,那麼自然要進行

反序列化

了,將二進位制的資料反序列化為請求物件,然後將這個請求物件交給Service B的Stub處理;

和之前的Service A的Stub一樣,這裡的Stub也同樣是個“假玩意”,它所負責的,只是去解析請求物件,知道呼叫方要調的是哪個RPC介面,傳進來的引數又是什麼,然後再把這些引數傳給對應的RPC介面,也就是Calculator的實際實現類去執行。很明顯,如果是Java,那這裡肯定用到了

反射

RPC介面執行完畢,返回執行結果,現在輪到Service B要把資料發給Service A了,怎麼發?一樣的道理,一樣的流程,只是現在Service B變成了Client,Service A變成了Server而已:Service B反序列化執行結果->傳輸給Service A->Service A反序列化執行結果 -> 將結果返回給Application,完畢。

總結:RPC包含了網路傳輸,序列化和反序列化,call id對映等。

參考連結:https://waylau。com/remote-procedure-c alls/

https://www。

jianshu。com/p/2accc2840

a1b

https://www。

jianshu。com/p/5b90a4e70

783