Protobuf 全稱:Google Protocol Buffers,由谷歌開源而來,經谷歌內部測試使用。它將數據結構以 .proto 文件進行描述,通過代碼生成工具可以生成對應數據結構的 POJO 對象和 Protobuf 相關的方法和屬性。
一、 Protocol 的特點
【1】在谷歌內部長期使用,產品成熟度高;
【2】高效的編解碼性能,編碼后的消息更小,有利於存儲和傳輸;
【3】語言無關、平台無關、擴展性好
【4】官方支持 Java、C++ 、C#、 Python 、Go 和 Dart
Protobuf 使用二進制編碼,在空間和性能上相對於 XML具有很大的優勢。盡量 XML的可讀性和可擴展性非常好,也非常適合描述數據結構,但是 XML 解析的時間開銷和 XML為了可讀性而犧牲的空間開銷都非常大,因此不適合做高性能的通信協議。
Protobuf 的數據描述文件和代碼生成機制(跨語言的編解碼框架,都具有此功能),優點如下:
■ 文本化的數據結構描述語言,可以實現語言和平台無關,特別適合異構系統間的集成;
■ 通過標識字段的順序,可以實現協議的前向兼容;
■ 自動代碼生成,不需要手工編寫同樣數據結構的 C++ 和 Java 版本;
■ 方便后續的管理和維護。相當於代碼,結構化的文檔更容易管理和維護。
Protobuf 的編解碼性能遠遠高於 JSON<Serializable<hession2<hession1<XStream<hession2壓縮(性能有高到底)等序列化框架的序列化和反序列化,這也是很多 RPC 框架選用 protobuf 做編解碼框架的原因。
二、Protobuf 開發環境搭建
【1】首先下載 Protobuf 的最新 Windown 版本:網站地址如下:https://github.com/protocolbuffers/protobuf/releases/tag/v3.9.1
官網對 java 編寫 .proto 文件,詳細說明地址:https://developers.google.cn/protocol-buffers/docs/javatutorial
下面我們定義一個 person.proto 數據文件。如下: 注釋寫在#號后,實際不能這么操作。此處為方便理解:
【2】通過 protoc.exe 命令行生成 Java 代碼,命令如下:[ --java_out=生成 *.java 文件的存放路徑,我所在的目錄正是存放person.proto 文件的目錄 ]沒有任何錯誤就說明生成成功。
【3】查看生成的目標文件:或者在外面生成好,拷貝進來也行。建議不要對生成的文件做任何修改。我們發現代碼編譯出錯,原因是因為少了 protobuf 的 jar 包:
引入 protobuf-java 相關的 jar 包,如下:
到此為止,Protobuf 開發環境已經搭建完畢,接下來進行示例展示。
三、Protobuf 編解碼開發
Protobuf 的類庫使用比較簡單,下面通過對 AddressBookProtos 編解碼來介紹 Protobuf 的使用:由於 Protobuf 支持復雜 POJO 對象編解碼,所以代碼都是通過工具自動生成,相比於傳統的 POJO 對象的賦值操作,其使用略微復雜一些。Protobuf 的編解碼接口非常簡單和實用,但是功能和性能卻非常強大,這也是它流行的一個重要原因。
四、Netty 的 Protobuf 服務端開發
【1】標准的服務端:主要區別在於 childHandler 方法中的 PersonChannelInitializer 類的內容。
【2】PersonChannelInitializer 內容展示:重點關注自定義 handler(PersonHandler)
【1】客戶端:主要區別在於 childHandler 方法中的 PersonClientInitializer 類的內容。
啟動服務端——>啟動客戶端,運行結果如下:
【1】服務端結果展示:
【2】客戶端結果展示:
七、問題
當 .proto 中存在多個 message 時,在解碼 ProtobufDecode(目標對象)中,添加的目標對象不唯一,會根據情況進行變化的問題及解決方案。
【1】.proto 文件內容如下:包含多個 message 對象。oneof 關鍵字表示:多個可選項,但允許選擇一個。設置的新值會替換掉舊值。