本文同步發佈於GitHub、我的主頁等html
smartbuf-dubbo
是一個基於smartbuf
的dubbo
序列化插件。java
它內部封裝了smartbuf
序列化框架的stream
模式,經過自定義的SmartbufSerialization
向dubbo
暴露了一個名爲smartbuf
的序列化器。git
smartbuf
smartbuf
是一種新穎、高效、智能、易用的跨語言序列化框架,它既擁有不亞於protobuf
的高性能,也擁有與json
相仿的通用性、可擴展性、可調試性等。github
它內部採用分區序列化將鬆散的對象序列化爲若干個緊湊的分區,從而大幅提升編碼效率,具體細節請參考smartbuf
項目。apache
smartbuf-dubbo
內部實現很是簡單,它只是簡單地按照dubbo
官方文檔提供了序列化插件,包括三個class
:json
SmartbufObjectInput
SmartbufObjectOutput
SmartbufSerialization
以及位於core/src/main/resources/META-INF.dubbo/
的插件配置。數組
此插件已打包deploy
至中心倉庫,因此你能夠直接經過如下maven
座標引入它:服務器
<dependency> <groupId>com.github.smartbuf</groupId> <artifactId>smartbuf-dubbo</artifactId> <version>1.0.1</version> </dependency>
固然也能夠直接將以上提到的class
和resources
配置複製入本身的工程中,同時記得手動添加smartbuf
依賴。網絡
以後就能夠按照官方文檔的配置,在protocol
中選擇啓用序列化插件,具體效果可能相似於:架構
<dubbo:protocol serialization="smartbuf" />
此插件支持com.alibaba
版本與org.apache
版本的dubbo
。
根目錄中的demo-alibaba
和demo-apache
分別針對2.6.*
版本和2.7.*
版本的dubbo
進行序列化測試,測試對象包括smartbuf
、fastjson
、hessian2
、kryo
、fst
。
對比測試包括三部分:tiny
、user
、posts
,分別對比測試各個序列化框架在簡單、普通、複雜業務中的綜合表現。
提示:對比測試側重於單線程的序列化性能、數據壓縮率,最終數據僅用於橫向對比各個序列化框架,並不能體現dubbo
自己的多併發性能。
posts
測試此測試中dubbo
接口返回的數據爲100
個固定的PostModel
實例,其具體模型以下:
public class PostModel implements Serializable { private int postId; private int authorId; private Integer prePostId; private String title; private String description; private ContentType contentType; private Visibility visibility; private long createTime; private List<Integer> mentions = new ArrayList<>(); private List<TopicModel> topics = new ArrayList<>(); }
測試中隨機建立100
個PostModel
對象、10
個TopicModel
對象,而後隨機爲每一個PostModel
分配若干個TopicModel
,最終模擬相似實際產品應用中的queryPost
結果集。
這個數據集採用json
編碼時,大概20KB
,各個序列化框架調用10w
次的綜合表現爲:
fastjson
: 耗時約192s
, 網絡輸入輸出總計約17.88GB
fst
: 耗時約52s
, 網絡輸入輸出總計約4.01GB
hessian2
: 耗時約115s
, 網絡輸入輸出總計約11.08GB
kryo
: 耗時約135s
, 網絡輸入輸出總計約4.05GB
smartbuf
: 耗時約75s
, 網絡輸入輸出總計約2.15GB
具體表現以下圖所示,橫軸表示時間,縱軸表示網絡流量:
說明:模型中存在枚舉值ContentType
與Visibility
,而測試中使用的kryo
並不支持枚舉,所以在測試kryo
時直接忽略了枚舉,最終致使它的測試數據並不完整。
user
測試此測試中dubbo
接口返回的數據爲1
個固定的UserModel
實例,其具體模型以下:
public class UserModel implements Serializable { private int id; private String token; private String nickname; private String loginIp; private long loginTime; private long createTime; private long updateTime; private List<UserModel> friends = new ArrayList<>(); }
爲了照顧kryo
,此測試中再也不使用enum
類型。
測試中爲friends
隨機建立20
個UserModel
對象,順便測試一下各個序列化框架對循環引用的處理。這個數據集採用json
編碼時,大概4KB
,各個序列化框架調用30w
次的綜合表現爲:
fastjson
: 耗時約41s
, 網絡輸入輸出總計約1.11GB
fst
: 耗時約31s
, 網絡輸入輸出總計約0.55GB
hessian2
: 耗時約32s
, 網絡輸入輸出總計約0.57GB
kryo
: 耗時約39s
, 網絡輸入輸出總計約0.62GB
smartbuf
: 耗時約41s
, 網絡輸入輸出總計約0.43GB
具體表現以下圖所示,橫軸表示時間,縱軸表示網絡流量:
tiny
測試此測試中dubbo
接口返回的數據爲一個普通的uuid
字符串,沒有太大的意義。各個序列化框架調用40w
次的綜合表現爲:
fastjson
: 耗時約46s
, 網絡輸入輸出總計約130MB
fst
: 耗時約38s
, 網絡輸入輸出總計約122MB
hessian2
: 耗時約38s
, 網絡輸入輸出總計約120MB
kryo
: 耗時約38s
, 網絡輸入輸出總計約120MB
smartbuf
: 耗時約42s
, 網絡輸入輸出總計約120MB
具體表現以下圖所示,橫軸表示時間,縱軸表示網絡流量:
以上測試所有爲本地網絡,使用的dubbo
版本號爲2.6.7
。
你能夠直接checkout
源代碼在本地執行測試代碼。測試中用於採集網絡IO
數據的NetMonitor
類內部使用了nettop
指令,據我瞭解它應該只支持osx
操做系統,若是你在其餘系統中執行測試,可能沒法得到正確的bytes_in
及bytes_out
。
因爲smartbuf
在架構設計上採用了數據可複用的分區序列化,所以面對大數據集、數組、列表等結構時,能夠經過屬性複用的技術優點,顯著地提升其編碼效率。相比於kryo
、fst
、hession2
等時,甚至能夠提升一倍的空間利用率,相比於json
更是提升一個數量級。
因爲smartbuf
底層設計上以相似於json的方式解析數據,所以它的兼容性與json
相仿,自然地解決了不一樣對象模型之間的字段兼容。且支持大多數經常使用的數據類型,也包括枚舉、泛型等等。相比之下其餘序列化框架僅支持java
語言,且存在或多或少的兼容性問題,以及支持數據類型過少的問題。好比測試中發現kryo
不支持enum
和AbstractList$SubList
。
在序列化性能上smartbuf
相比於fst
存在一些劣勢,多是分區序列化中內存複製所致,也多是代碼中某些地方存在性能問題。不過這種劣勢每每只是納秒級的,相比於數據報文在服務器、機房、區域的網絡傳輸而言,都是微不足道的。