序列化:把對象轉換爲字節序列的過程稱爲對象的序列化。
反序列化:把字節序列恢復爲對象的過程稱爲對象的反序列化。
Dubbo是 Alibaba 開源的分佈式服務框架遠程調用框架,現在已捐贈給 apache 軟件基本會。因此 dubbo 調用是需要跨 JVM,需要進行網絡通信。這就需要使用到序列化與反序列化。在 dubbo 中定義了 ObjectInput、ObjectOutput 與 Serialization 來進行數據的序列化與反序列化。
1、Serialization 定義
下面我們來看一下 Serialization 的接口定義:
@SPI("hessian2")
public interface Serialization {
byte getContentTypeId();
String getContentType();
@Adaptive
ObjectOutput serialize(URL url, OutputStream output) throws IOException;
@Adaptive
ObjectInput deserialize(URL url, InputStream input) throws IOException;
}
這個接口裏面定義了 4 個方法:
- getContentTypeId:獲取序列化 ContextType 的 id。
- getContentType:獲取到序列化的 ContentType。
- serialize:創建一個 ObjectOutput (序列化器),用於把對象轉換序列化字節序列.
- deserialize:創建一個 ObjectInput (反序列化器),用於把字節序列恢復成對象.
2、支持多種序列化
下面是 Serialization 的類圖:
dubbo 支持多種序列化方式並且序列化是和協議相對應的。比如:dubbo協議的 dubbo, hessian2,java,compactedjava,rmi協議缺省爲java,以及http協議的json等。
- dubbo序列化:阿里尚未開發成熟的高效java序列化實現,阿里不建議在生產環境使用它
- hessian2序列化:hessian是一種跨語言的高效二進制序列化方式。但這裏實際不是原生的hessian2序列化,而是阿里修改過的hessian lite,它是dubbo RPC默認啓用的序列化方式
- json序列化:目前有兩種實現,一種是採用的阿里的fastjson庫,另一種是採用dubbo中自己實現的簡單json庫,但其實現都不是特別成熟,而且json這種文本序列化性能一般不如上面兩種二進制序列化。
- java序列化:主要是採用JDK自帶的Java序列化實現,性能很不理想。
這四種主要序列化方式的性能從上到下依次遞減。對於dubbo RPC這種追求高性能的遠程調用方式來說,實際上只有1、2兩種高效序列化方式比較般配,而第1個 dubbo 序列化由於還不成熟,所以實際只剩下2可用,所以dubbo RPC默認採用 hessian2 序列化。
但 hessian 是一個比較老的序列化實現了,而且它是跨語言的,所以不是單獨針對java進行優化的。而dubbo RPC實際上完全是一種Java to Java的遠程調用,其實沒有必要採用跨語言的序列化方式(當然肯定也不排斥跨語言的序列化)。
最近幾年,各種新的高效序列化方式層出不窮,不斷刷新序列化性能的上限,最典型的包括:
- 專門針對Java語言的:Kryo,FST等等
- 跨語言的:Protostuff,ProtoBuf,Thrift,Avro,MsgPack等等
這些序列化方式的性能多數都顯著優於 hessian2 (甚至包括尚未成熟的dubbo序列化)。所以我們可以
爲 dubbo 引入 Kryo 和 FST 這兩種高效 Java 來優化 dubbo 的序列化。
使用Kryo和FST非常簡單,只需要在dubbo RPC的XML配置中添加一個屬性即可:
<dubbo:protocol name="dubbo" serialization="kryo"/>
或者
<dubbo:protocol name="dubbo" serialization="fst"/>
3、序列化擴展
可以通過擴展 Serialization、ObjectInput、ObjectOutput 來進行 dubbo 序列化的擴展。
擴展示例
Maven 項目結構:
src
|-main
|-java
|-com
|-xxx
|-XxxSerialization.java (實現Serialization接口)
|-XxxObjectInput.java (實現ObjectInput接口)
|-XxxObjectOutput.java (實現ObjectOutput接口)
|-resources
|-META-INF
|-dubbo
|-com.alibaba.dubbo.common.serialize.Serialization (純文本文件,內容爲:xxx=com.xxx.XxxSerialization)
XxxSerialization.java:
package com.xxx;
import com.alibaba.dubbo.common.serialize.Serialization;
import com.alibaba.dubbo.common.serialize.ObjectInput;
import com.alibaba.dubbo.common.serialize.ObjectOutput;
public class XxxSerialization implements Serialization {
public ObjectOutput serialize(Parameters parameters, OutputStream output) throws IOException {
return new XxxObjectOutput(output);
}
public ObjectInput deserialize(Parameters parameters, InputStream input) throws IOException {
return new XxxObjectInput(input);
}
}
META-INF/dubbo/com.alibaba.dubbo.common.serialize.Serialization:
xxx=com.xxx.XxxSerialization
並且通過以下配置來使用新的擴展。
<!-- 協議的序列化方式 -->
<dubbo:protocol serialization="xxx" />
<!-- 缺省值設置,當<dubbo:protocol>沒有配置serialization時,使用此配置 -->
<dubbo:provider serialization="xxx" />
參考資料: