在序列化技術(shù)中娶耍,除了java提供的序列化免姿,還有很多其他的序列化技術(shù)。對于java而已榕酒,java序列化是由java語言自帶的胚膊,使用比較方便簡單。但是相對于優(yōu)勢想鹰,缺點也是很明顯的紊婉,首先就是不支持跨語言擴展、性能相對不是很好辑舷、序列化以后產(chǎn)生的數(shù)據(jù)相對會比較大喻犁。
然后除了java自帶的序列化,還有以下的一些序列化技術(shù)何缓。
1.xml序列化框架
xml的好處在于可讀性好肢础,方便閱讀還有調(diào)試。但是序列化以后碌廓,字節(jié)碼文件比較大传轰,而且效率不高,適用對性能要求不高谷婆,而且QPS較低的企業(yè)級內(nèi)部之間的數(shù)據(jù)交換的場景慨蛙,同時xml又具有語言無關(guān)性,所以還可以適用于異構(gòu)系統(tǒng)之間的數(shù)據(jù)交換協(xié)議纪挎。比如webService期贫,就是采用xml格式對數(shù)據(jù)進行序列化的遏片。
代碼實現(xiàn)如下:
導(dǎo)入依賴
<!--xml序列化-->
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.10</version>
</dependency>
實現(xiàn)序列化和反序列化的類
public class ZmlSerializer implements ISerializer {
XStream xStream=new XStream(new DomDriver());
@Override
public <T> byte[] serializer(T obj) {
return xStream.toXML(obj).getBytes();
}
@Override
public <T> T deSerializer(byte[] data, Class<T> clazz) {
return (T) xStream.fromXML(new String(data));
}
}
測試類:
public static void main(String[] args) {
User user = new User("s",12);
ISerializer xmlSerializer = (ISerializer) new ZmlSerializer();
byte[] serializer = xmlSerializer.serializer(user);
System.out.println(new String(serializer));
User user1 = xmlSerializer.deSerializer(serializer, User.class);
System.out.println(user1);
}
2.JSON序列化框架
JSON(JavaScript Object Notation)是一種輕量級的數(shù)據(jù)交換格式涮俄,相對于XML 來說,JSON 的字節(jié)流更小前域,而且可讀性也非常好】就桑現(xiàn)在JSON數(shù)據(jù)格式在企業(yè)運用是最普遍的埠帕,就是將數(shù)據(jù)對象轉(zhuǎn)換成json對象。
JSON 序列化常用的開源工具有很多
- Jackson (https://github.com/FasterXML/jackson)
- 阿里開源的FastJson (https://github.com/alibaba/fastjon)
- Google 的GSON (https://github.com/google/gson)
這幾種json 序列化工具中玖绿,Jackson 與fastjson 要比GSON 的性能要好,但是Jackson叁巨、GSON 的穩(wěn)定性要比Fastjson 好斑匪。而fastjson 的優(yōu)勢在于提供的api 非常容易使用。
3.Hessian 序列化框架
Hessian 是一個支持跨語言傳輸?shù)亩M制序列化協(xié)議,相對于Java 默認(rèn)的序列化機制來說蚀瘸,Hessian 具有更好的性能和易用性狡蝶,而且支持多種不同的語言實際上Dubbo 采用的就是Hessian 序列化來實現(xiàn),只不過Dubbo 對Hessian 進行了重構(gòu)贮勃,性能更高贪惹。
這是一種支持動態(tài)類型、跨語言寂嘉、基于對象傳輸?shù)木W(wǎng)絡(luò)協(xié)議奏瞬。JAVA對象序列化的二進制流是可以被其他語言反序列化的。hessian協(xié)議具有如下特性:
1.自描述序列化類型泉孩,不依賴外部描述符或接口定義硼端,用一個字節(jié)表示常用的基礎(chǔ)類型,極大縮短二進制流寓搬。
2.跟語言無關(guān)珍昨,支持腳本語言
3.協(xié)議比較簡單,比java原生的要高效很多句喷。在hessian2.0進行升級后镣典,新增了一個壓縮編碼,而序列化的二進制流是java序列化的50%唾琼,耗時是java序列化的30兄春,而反序列化是其20%。
hessian序列化會把復(fù)雜對象所有熟悉存在一個map中父叙,進行序列化神郊。所以在父類、子類存在同名變量的情況下趾唱,hessian序列化時涌乳,先序列化子類,再序列化父類甜癞,因此序列化的結(jié)果會導(dǎo)致子類同名變量被父類的覆蓋夕晓。
4.Protobuf 序列化框架(重點,一般接觸比較少)
1.獨立語言悠咱,獨立平臺蒸辆。不同語言有不同的序列化方式。
2.Protobuf是一個基于表示層的協(xié)議析既,可以跟各種協(xié)議一起使用躬贡。
3.空間開銷,性能眼坏,解析性能都要好拂玻。
缺點:
實現(xiàn)比較麻煩,有獨立的編譯器,要考慮學(xué)習(xí)的成本檐蚜。
https://github.com/google/protobuf/releases 找到 protoc-3.5.1-win32.zip
看看怎么實現(xiàn)以及語法:
syntax="proto2";
package com.zxy.serial;
option java_package = "com.zxy.serial";
option java_outer_classname="UserProtos";
message User {
required string name=1;
required int32 age=2;
}
proto 的語法
- 包名
- option 選項
- 消息模型(消息對象魄懂、字段(字段修飾符-required/optional/repeated)
字段類型(基本數(shù)據(jù)類型、枚舉闯第、消息對象)市栗、字段名、標(biāo)識號)
生成實體類
在protoc.exe 安裝目錄下執(zhí)行如下命令
.\protoc.exe --java_out=./ ./user.proto
運行查看結(jié)果
將生成以后的UserProto.java 拷貝到項目中
Protobuf 原理分析
核心原理: protobuf 使用varint(zigzag)作為編碼方式咳短, 使用T-LV
作為存儲方式.
技術(shù)層面
- 序列化空間開銷填帽,也就是序列化產(chǎn)生的結(jié)果大小,這個影響到傳輸?shù)男阅?/li>
- 序列化過程中消耗的時長诲泌,序列化消耗時間過長影響到業(yè)務(wù)的響應(yīng)時間
- 序列化協(xié)議是否支持跨平臺盲赊,跨語言。因為現(xiàn)在的架構(gòu)更加靈活敷扫,如果存在異構(gòu)系統(tǒng)通信需求哀蘑,那么這個是必須要考慮的
- 可擴展性/兼容性,在實際業(yè)務(wù)開發(fā)中葵第,系統(tǒng)往往需要隨著需求的快速迭代來實現(xiàn)快速更新绘迁,這就要求我們采用的序列化協(xié)議基于良好.的可擴展性/兼容性,比如在現(xiàn)有的序列化數(shù)據(jù)結(jié)構(gòu)中新增一個業(yè)務(wù)字段卒密,不會影響到現(xiàn)有的服務(wù)
- 技術(shù)的流行程度缀台,越流行的技術(shù)意味著使用的公司多,那么很多坑都已經(jīng)淌過并且得到了解決哮奇,技術(shù)解決方案也相對成熟
- 學(xué)習(xí)難度和易用性.
選型建議
- 對性能要求不高的場景膛腐,可以采用基于XML 的SOAP 協(xié)議
- 對性能和間接性有比較高要求的場景,那么Hessian鼎俘、Protobuf哲身、Thrift、
Avro 都可以贸伐。 - 基于前后端分離勘天,或者獨立的對外的api 服務(wù),選用JSON 是比較好的捉邢,對于調(diào)試脯丝、可讀性都很不錯
- Avro 設(shè)計理念偏于動態(tài)類型語言,那么這類的場景使用Avro 是可以的.