1 對象序列化/反序列化簡介
在實(shí)際開發(fā)中食棕,為了簡化開發(fā)寿弱,通常請求和響應(yīng)都使用使用Java對象表示渗磅,對使用者屏蔽底層的協(xié)議細(xì)節(jié)嚷硫。例如一些RPC框架,支持把用戶定義的Java對象當(dāng)做參數(shù)去請求服務(wù)端始鱼,服務(wù)端響應(yīng)也是一個Java對象仔掸。
而前面我們講解的案例都是以字符串作為請求和響應(yīng)參數(shù),實(shí)際上医清,Netty對于我們的自定義的Java對象作為請求響應(yīng)參數(shù)也是支持的起暮,其默認(rèn)支持通過以下機(jī)制對Java對象進(jìn)行序列化和反序列化:
- ObjectEncoder/ObjectDecoder:使用JDK序列化機(jī)制編解碼
- ProtobufEncoder/ ProtobufDecoder:使用google protocol buffer進(jìn)行編解碼
- MarshallingEncoder/MarshallingDecoder:使用JBoss Marshalling進(jìn)行編解碼
- XmlDecoder:使用Aalto XML parser進(jìn)行解碼,將xml解析成Aalto XML parser中定義的Java對象会烙,沒有提供相應(yīng)的編碼器
- JsonObjectDecoder:使用Json格式解碼负懦。當(dāng)檢測到匹配數(shù)量的"{" 、”}”或”[””]”時持搜,則認(rèn)為是一個完整的json對象或者json數(shù)組密似。這個解碼器只是將包含了一個完整Json格式數(shù)據(jù)的ByteBuf實(shí)例交給之后的ChannelInbounderHandler解析,因此我們需要依賴其他的JSON框架葫盼,如Gson残腌、jackson、fastjson等贫导。沒有提供相應(yīng)的編碼器抛猫。
除了Netty默認(rèn)值支持的這些序列化機(jī)制,事實(shí)上還有很多的其他的序列化框架孩灯,如:hessian
闺金、Kryo
、Avro
峰档、fst
败匹、msgback
寨昙、thrift
、protostuff
等掀亩。
在實(shí)際開發(fā)中舔哪,通常我們沒有必要支持上述所有的序列化框架,支持部分即可槽棍。主要的選擇依據(jù)如下表:
選擇依據(jù) | 說明 |
---|---|
效率 | 即序列化和反序列化的性能捉蚤。這方面Kryo、Avro炼七、fst缆巧、hessian等都不錯。 |
序列化后的占用字節(jié)數(shù) | 對于同一個Java對象豌拙,不同的框架序列化后占用的字節(jié)數(shù)不同陕悬。例如JDK序列化體積較大,而Kryo的體積較小姆蘸。體積過大的話墩莫,會增加網(wǎng)絡(luò)帶寬壓力。 |
是否有可視化需求 | json逞敷、xml序列化機(jī)制的結(jié)果能以文本形式展示;但是其他的框架大多是二進(jìn)制的灌侣,因此可視化推捐。 |
開發(fā)成本 | 一些序列化框架使用較為復(fù)雜,如thrift侧啼、protocol buffer牛柒;另外則很簡單,如JDK序列化痊乾、Hessian等 |
從本教程而言皮壁,主要是為了介紹如何在Netty中使用這些序列化框架,方式類似哪审,因此不會對每一種都進(jìn)行介紹蛾魄。在后續(xù)的文章中,我們將會對:JDK序列化湿滓、Hessian序列化滴须、protocol buffer序列化進(jìn)行講解。
2 通信協(xié)議格式要求
另外一點(diǎn)需要注意的是叽奥,上面提到的這些序列化框架通常不能單獨(dú)使用扔水。例如發(fā)送方只是將Java對象序列化成二進(jìn)制字節(jié),對于接收方而言朝氓,則無法判斷到底哪些字節(jié)可以構(gòu)成一個完整的Java對象魔市,也就無法反序列化主届。因此我們通常需要結(jié)合長度編碼,可以使用上一節(jié)提到的LengthFieldBasedFrameDecoder/LengthFieldPrepender來協(xié)助完成待德。
最簡單的通信協(xié)議格式如下:
+--------+----------+
| Length | Content |
+--------+----------+
其中:
- Length:表示Content字段占用的字節(jié)數(shù)君丁,Length本身占用的字節(jié)數(shù)我們可以指定為一個固定的值。
- Content:對象經(jīng)過序列化后二進(jìn)制字節(jié)內(nèi)容
對于上述協(xié)議磅网,通常我們只能選擇支持一種序列化框架谈截,如果要支持多個序列化框架,我們可以對通信協(xié)議格式稍作改造涧偷,增加一個字段來表示使用的序列化框架簸喂,如:
+--------+-------------+------------+
| Length | Serializer | Content |
+--------+-------------+------------+
其中:Serializer我們可以指定使用1個字節(jié)表示,因此可以有256個值可選燎潮,我們用不同的值代表不同的框架喻鳄。在編碼時,選擇好序列化框架后确封,進(jìn)行序列化除呵,并指定Serializer字段的值。在解碼時爪喘,根據(jù)Serializer的值選擇對應(yīng)的框架進(jìn)行反序列化颜曾;
在后面的章節(jié)中,讓我們開啟對象的序列化/反序列化之旅秉剑!