編解碼技術

2020-08-08 15:43:20

1.Java的編解碼技術含義

將java物件編碼爲位元組陣列寫入檔案,或用於網路傳輸,在讀取檔案或者接受數據的時候,將其再解碼爲java物件。

從而引出Java進行編解碼的目的:

  • 網路傳輸
  • 物件持久化

java的序列化(實現Serializable介面)是java編解碼技術中的一種實現方式。java序列化技術有以下缺陷:

  1. java序列化技術使用內部私有協定,無法跨語言
  2. 序列化後的位元組碼陣列太大;
  3. 序列化的效能太低,耗時長;

因此,遠端服務呼叫(RPC)不直接使用java原生序列化技術。也正是因爲這些原因,衍生了很多編解碼技術和框架。

2.主流的編解碼框架

評價編解碼框架的優劣,我們主要從以下幾點考慮:

  • 是否支援跨語言,支援的語言型別;
  • 編碼後的碼流大小;
  • 編解碼的效能;
  • 類庫的大小,api使用是否方便;
  • 二次開發的工作量和難度;

2.1 Google 的 Protobuf

Protobuf 全稱 Google Protocol Buffers,它由谷歌開源而來。它將數據結構以.proto 檔案進行描述,通過程式碼生成工具可以生成對應數據結構的 POJO 物件和 Protobuf 相關的方法和屬性。特點:

  • 結構化數據儲存格式(XML,JSON 等)
  • 高效的編解碼效能
  • 語言無關、平臺無關、擴充套件性好
  • 支援 Java、C++ 、Python、Objective-C、C# 、JavaScript、Ruby、Go、PHP、Dart多種語言

Protocol Buffers 是一種輕便高效的結構化數據儲存格式,可以用於結構化數據序列化。它很適合做數據儲存或 RPC 數據交換。
Protobuf 在 Github 開源地址:https://github.com/protocolbuffers/protobuf

Protobuf 另一個吸引人的是它的數據描述檔案和程式碼生成機制 機製。利用數據描述檔案對數據結構進行說明,其優點如下:

  • 文字話的數據結構描述語言,可以實現語言和平臺無關,特別適合異構系統間的整合
  • 通過標識欄位的順序,可以實現協定的前後相容
  • 欄位程式碼生成,不需要手工編寫同樣數據結構的 C++ 和 Java 版本
  • 方便後續的管理和維護,相比於程式碼,結構化的文件更易管理和維護

2.2 Facebook 的 Thrift

Thrift 源於 Facebook,在 2007 年 Facebook 將 Thrift 作爲一個開源專案提交給 Apache 基金會。對於當時的 Facebook 來說,創造 Thrift 是爲了解決 Facebook 各系統間大數據量的傳輸通訊以及系統之間語言環境不同需要跨平臺的特性,因此 Thrift 可以支援多種程式語言,如 C++、C#、Cocoa、Erlang、Haskell、Java、Ocami、Perl、PHP、Python、Ruby 和 Smalltalk。

在多種不同的語言之間通訊,Thrift 可以作爲高效能的通訊中介軟體使用,它支援數據(物件)序列化和多種型別的 RPC 服務。Thrift 適用於靜態的數據交換,需要先確定好它的數據結構,當數據結構發生變化時,必須重新編輯 IDL 檔案,生成程式碼和編譯,這一點跟其他 IDL 工具相比可以視爲是 Thrift 的弱項。Thrift 適用於搭建大型數據交換及儲存的通用工具,對於大型系統中的內部數據傳輸,相對於 JSON 和 XML 在效能和傳輸大小上都有明顯的優勢。

與 Protobuf 比較類似的是,Thrift 通過 IDL 描述介面和數據結構定義,它支援 8 種 Java 基本型別、Map、Set 和 List,支援可選和必選定義,功能非常強大。因爲可以定義數據結構中欄位的順序,所以它也可以支援協定的前向相容。

Thrift 支援三種比較典型的編解碼方式:

  1. 通用的二進制編解碼;
  2. 壓縮二進制編解碼;
  3. 優化的可選欄位壓縮編解碼。

由於支援二進制壓縮編解碼,Thrift 的編解碼效能表現也相當優異,遠遠超過 Java 序列化和 RMI 等。

2.3 Jboos 的 Marshaling

JBoss Marshalling 是一個 Java 物件的序列化 API 包,修正了 JDK 自帶的序列化包的很多問題,但又保持跟 java.io.Serializable 介面的相容;同時增加了一些可調的參數和附加的特性,並且這些參數和特性可通過工廠類進行設定。
相比於傳統的 Java 序列化機制 機製,它的優點如下:

  • 可插拔的類解析器,提供更加便捷的類載入定製策略,通過一個介面即可實現定製;
  • 可插拔的物件替換技術,不需要通過繼承的方式;
  • 可插拔的預定義類快取表,可以減小序列化的位元組陣列長度,提升常用型別的物件序列化效能;
  • 無須實現 java.io.Serializable 介面,即可實現 Java 序列化;
  • 通過快取技術提升物件的序列化效能。

相比於前面介紹的兩種編解碼框架,JBoss Marshalling 更多是在 JBoss 內部使用,應用範圍有限。

Marshalling 在 GitHub 開源地址:https://github.com/jboss-remoting/jboss-marshalling

2.4 MessagePack

像 JSON,但是更快更小。
MessagePack 是一種高效的二進制序列化格式。它允許在 JSON 等多種語言之間交換數據,但它更快速更小巧。小整數被編碼爲單個位元組,典型的短字串除了字串本身之外只需要一個額外的位元組。MessagePack 支援主流的 50 多種程式語言。
MessagePack Java 模組 GitHub 開源地址:https://github.com/msgpack/msgpack-java

核心壓縮方式官方說明:https://github.com/msgpack/msgpack/blob/master/spec.md

2.5 其他編解碼框架

除了上述介紹的編解碼框架和技術之外,比較常用的還有 kryo、hession 和 Json 等。

3.總結

實際應用中,是否序列化物件進行傳遞以及使用哪種編解碼框架還是需要應該根據需求而定,有時候發送字串也是挺方便的,比如一個 POJO 物件,或者 Map、List 等,可以先使用 Gson、FastJson 等庫將物件序列化爲 Json 字串,然後發送 json 字串數據,接收的時候,再用 Gson、FastJson 反序列化,將 json 字串轉爲物件即可。