首頁>技術>

在設計或重構系統的過程中,特別是在設計分散式、大資料量系統裡面,序列化選型是一個重要環節,因為序列化協議影響系統的通用性、健壯性、安全性,是否易於除錯、是否便於擴充套件。

序列化分理論和實踐部分,理論部分描述只序列化是什麼、要做什麼,不關心實現(因為不考慮具體實現,所以自然不會考慮優缺點、應用場景);實踐部分描述如何完成序列化操作,物件用什麼方法表示,即把序列化從理論世界帶進現實世界。序列化理論部分相當於是設計,實踐部分相當於實現。

理論

序列化理論包含的三個方面序列化定義;序列化在通訊協議中的地位;序列化元件1. 序列化問題是怎麼產生的(序列化的定義)

網際網路的發展產生了機器之間互相通訊的需求,機器之間互相通訊需要約定通訊協議,通訊協議又要考慮資料如何表示、如何傳輸等問題。序列化就是通訊協議裡與資料的表示相關的那一部分協議。OSI七層協議模型中的展現層(Presentation Layer)的主要功能是把物件轉換成一段連續的二進位制串,或把二進位制串轉換成物件–這就是序列化和反序列化。

所以,序列化和反序列化的定義就是:

序列化: 將資料結構或物件轉換成二進位制串反序列化:將在序列化過程中所生成的二進位制串轉換成資料結構或物件

注:不一定非要轉換成二進位制,只要是能傳輸到通訊另一端都可以,例如utf-8字串。

2. 序列化在通訊協議中的地位OSI七層協議模型,序列化位於展示層(Presentation Layer)在TCP/IP協議中,序列化位於應用層。3. 序列化和反序列化的元件

完整的序列化協議包含以下元件:

IDL檔案(Interface description language)。參與通訊的各方需要對通訊的內容做相關約定。為了與語言和平臺無關,這個約定需要採用與程式語言、平臺無關的語言來進行描述。這種語言被稱為介面描述語言(IDL),採用IDL撰寫的協議約定稱為IDL檔案。IDL Compiler:IDL檔案中的約定需要一個編譯器,將IDL檔案轉換成各程式語言的動態庫。Stub/Skeleton Lib:負責序列化和反序列化工作的程式碼。Stub是一段部署在客戶端的程式碼,一方面接收應用層的引數,並對其序列化後透過底層協議棧傳送到服務端;另一方面接收服務端序列化後的結果資料,反序列化後交給應用層;Skeleton部署在服務端,其功能與Stub相反,從傳輸層接收序列化引數,反序列化後交給服務端應用層,並將應用層的執行結果序列化後最終傳送給客戶端。

序列化元件之間的互動關係:

序列化元件之間的互動

序列化元件的概念與資料庫的相關概念類似:

實踐

序列化協議的考慮點支援哪些程式語言,能否跨語言支援哪些平臺,是否跨平臺(例如支援哪些硬體架構、作業系統)流行程度(序列化涉及通訊雙方,冷門的序列化協議需要的學習成本很高)健壯性/魯棒性成熟程度(這個協議是否經歷大量全面的測試、真實世界系統的檢驗,長期穩定執行)是否簡單易用除錯難度、可讀性(序列化和反序列化的資料正確性和業務正確性的除錯往往需要很長時間,良好的除錯機制大大提高開發效率。序列化後的二進位制串往往不具備人眼可讀性,為了驗證序列化結果的正確性,寫入方不得不同時撰寫反序列化程式,或提供一個查詢平臺–這比較費時;另一方面,如果讀取方未能成功實現反序列化,難以確定是自身反序列化程式bug導致的還是寫入方寫入了錯誤序列化資料導致的。如果序列化後的資料人眼可讀,這將大大提高除錯效率, 例如XML和JSON就具有人眼可讀的優點。)空間效能(Verbosity),即序列化以後的資料所佔用的空間大小。時間效能(Complexity)。複雜的序列化協議會導致較長的解析時間,這可能使得序列化和反序列化成為系統瓶頸。擴充套件性/相容性。新增欄位是否容易。業務系統需求的更新週期快,新需求不斷湧現。如果序列化協議具有良好的可擴充套件性,支援自動增加新的業務欄位,而不影響老的服務,這將大大提供系統的靈活度。安全性/訪問限制。例如阿里的fastjson經常有安全性問題。文件。已知的序列化協議

網際網路早期序列化協議有COM和CORBA。

COM主要用於Windows平臺,沒有實現跨平臺。COM序列化利用了編譯器中的虛表,使得學習成本很高。序列化得到的資料與編譯器緊耦合,擴充套件屬性非常麻煩。

CORBA比較好的實現了跨平臺,跨語言。COBRA的主要問題是參與方過多,導致版本過多,版本之間相容性差,使用複雜晦澀。早期設計的不成熟問題導致COBRA漸漸消亡。J2SE 1.3之後的版本提供基於CORBA協議的RMI-IIOP技術,可以採用純Java語言進行CORBA開發。

XML序列化協議

XML是一種語言,一種描述性的語言,最初目標是對文件進行編碼,而且要求編碼資料既能供人閱讀也便於計算機處理。XML在設計的時候就考慮到可讀性,它還有跨機器、跨語言(這裡指的是人類語言)等優點。XML歷史悠久,其1.0版本早在1998年就形成標準,並被廣泛使用至今,所以XML是足夠成熟的。既然XML能把有複雜結構的文件編碼,那麼XML也可以用於物件序列化,所以把XML列為一種序列化協議(例如.NET框架和gSOAP框架就採用XML序列化)。但是XML用作序列化協議的時候,它就顯得冗長複雜

XML具有自我描述性,XML自身就作為IDL。XML中的IDL(即XML描述格式)有兩種:DTD(Document Type Definition)和XSD(XML Schema Definition)。XML在某些程式語言裡面具有非常簡單易用的序列化API,無需IDL檔案和第三方IDL編譯器(例如Java XStream)。XML被廣泛應用在各種配置檔案中,例如O/R mapping、 Spring Bean Configuration File 等。

優點:跨平臺、跨語言、成熟、可讀性

缺點:複雜冗長(空間複雜度)

SOAP序列化協議

SOAP(Simple Object Access protocol)是一種廣泛應用的,基於XML的結構化訊息傳遞協議,XML被用於序列化和反序列化。SOAP支援多種傳輸協議,但是最常用的還是HTTP。SOAP協議的IDL是WSDL(Web Service Description Language)。

假如java應用層物件是:

用WSDL描述上述物件:

SOAP具有安全、可擴充套件、跨語言、跨平臺、支援多種傳輸協議,有廣泛的群眾基礎,基於HTTP的傳輸協議使得SOAP在穿越防火牆時具有良好安全性,XML的人眼可讀特性使得其具有出眾的可除錯性,網際網路頻寬的發展逐漸彌補了其空間開銷大的缺點。對於在公司之間傳輸少量資料或實時性要求相對低(例如秒級別),SOAP是一個好的選擇。

XML空間開銷大,資料量大、需要持久化應用場景不適合用XML。XML的序列化和反序列化的空間和時間開銷都比較大,對於對效能要求達到ms級別的服務,不推薦XML。WSDL雖然具備物件描述能力,但是SOAP的使用不簡單。對於習慣於面向物件程式設計的使用者,WSDL檔案不直觀。

JSON序列化協議

權威網站:http://json.com/

JSON起源於JavaScript中的”Associative array”的概念,本質就是採用”Attribute-value”方式描述物件。實際上在Javascript和PHP等弱型別語言中,類的描述方式就是Associative array。JSON有如下優點,使得它快速成為最廣泛使用的序列化協議之一:

1、這種Associative array格式匹配工程師對物件的理解。

2、它也有XML的人眼可讀(Human-readable)優點。

3、序列化後的資料簡潔

4、JavaScript先天支援,所以廣泛應用於Web browser的應用常景,是Ajax的事實標準協議。

5、與XML相比,其協議比較簡單,解析速度比較快。

6、鬆散的Associative array使得其具有良好的可擴充套件性和相容性。

因為json其實是associative array,與弱型別程式語言中的class在概念上對應,所以JSON序列化也不需要IDL。原因:IDL的目的是撰寫IDL檔案,而IDL檔案被IDL Compiler編譯後產生一些程式碼(Stub/Skeleton),而這些程式碼真正負責相應的序列化和反序列化工作。 但是由於Associative array和一般語言裡面的class太相似,他們之間形成了一一對應關係,這就使得我們可以採用一套標準程式碼進行相應的轉化。對於自身支援Associative array的弱型別語言,語言自身就具備操作JSON序列化後的資料的能力;對於Java這強型別語言,可以用反射解決。

JSON在很多應用場景中可以替代XML,更簡潔且解析速度更快。典型應用場景包括:

公司之間傳輸資料量相對小,實時性要求相對低(例如秒級別)的服務。基於Web browser的Ajax請求。由於JSON具有非常強的前後相容性,所以它適用於:介面經常發生變化,對可調式性要求高的場景,例如Mobile app與服務端的通訊(移動APP為什麼要用JSON協議與服務端互動)。JSON的典型應用場景是JSON+HTTP,適合跨防火牆訪問。

總體看,JSON序列化的額外空間開銷也比較大(但是比XML小多了),不適合資料量大或需要持久化的場景。沒有統一的IDL降低了對參與方的約束,實際操作中往往只能採用文件方式來進行約定,這可能會給除錯帶來一些不便,延長開發週期。由於JSON在一些語言中的序列化和反序列化需要反射機制,所以效能要求ms級別的系統不建議使用。

Thrift序列化協議

Thrift是Facebook開發的一個RPC框架,滿足了大資料量、分散式、跨語言、跨平臺資料通訊的需求。Thrift內部有一個自定義的序列化協議,即Thrift序列化協議。

優點:相對於JSON和XML,Thrift在空間開銷和解析效能上有較大提升,適用於效能要求高的系統;它支援多種程式語言,資料型別豐富,對於資料欄位的增刪有較強的相容性。

缺點:thrift序列化被嵌入到thrift框架內部,然而Thrift框架沒有對外提供thrift序列化和反序列化的介面,文件匱乏,用起來比較困難。Thrift序列化之後得到的資料是Binary陣列,不具有可讀性,除錯相對困難。Thrift的序列化和框架緊耦合,無法支援向持久層直接讀寫資料,不適合用於資料持久化的場景。

Protobuf序列化協議

權威網站:https://developers.google.com/protocol-buffers

Protobuf具備序列化協議的眾多優秀特徵:

提供了標準的IDL和IDL編譯器,對工程師非常友好。序列化資料簡潔緊湊,其序列化之後的資料量約為XML的1/3到1/10。解析速度非常快,比XML快約20-100倍。提供了友好的動態庫,使用非常簡潔,反序列化只需要一行程式碼。Protobuf IDL檔案對於各個參與方業務產生了強力的約束Protobuf與傳輸層無關,採用HTTP,具有良好的跨防火牆訪問屬性。

Protobuf是一個純展示層協議,可以用於多種傳輸層協議;Protobuf文件也非常完善。目前僅支援Java、C++、Python三種程式語言。另外Protobuf支援的資料型別較少,不支援常量。

所以Protobuf適用於跨公司、效能要求高的RPC呼叫應用場景。基於相同的原因,Protobuf也適合用於物件的持久化。

缺點:支援語言較少,沒有繫結標準傳輸層協議,跨公司進行傳輸層協議除錯相對麻煩。

Google gPRC框架已採用Protobuf序列化協議,可以參考。

Hessian序列化協議

hessian也是一種常見的序列化協議,經常在RPC框架中使用,例如Dubbo、Pigeon等框架都支援Hessian,甚至經常被RPC框架用作預設序列化方案。

Avro序列化協議

Avro是Apache Hadoop的子專案,解決了JSON的冗長和沒有IDL的問題。Avro提供兩種序列化格式:JSON格式和Binary格式。Binary格式在空間開銷和解析效能方面可以和Protobuf媲美,JSON格式方便除錯。Avro支援的資料型別非常豐富,包括C++語言裡面的union型別。Avro支援JSON格式的IDL和類似於Thrift和Protobuf的IDL(實驗階段),這兩者之間可以互轉。Schema可以在傳輸資料的同時傳送,加上JSON的自我描述屬性,使得Avro非常適合動態型別語言。Avro在做檔案持久化的時候,一般會和Schema一起儲存,所以Avro序列化檔案自身具有自我描述屬性,所以適合做Hive、Pig和MapReduce的持久化資料格式。對於不同版本的Schema,在進行RPC呼叫的時候,服務端和客戶端可以在握手階段對Schema進行互相確認,提高了資料解析的速度。Avro解析效能高且序列化資料簡潔,適合高效能序列化服務。

序列化協議Benchmark

資料 https://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking

解析效能

序列化之空間開銷

1、XML序列化(Xstream)無論在效能和簡潔性上都比較差。

2、Thrift與Protobuf相比在時空開銷方面都有一定劣勢。

3、Protobuf和Avro在兩方面表現都非常優越。

序列化協議的選型

以上幾種序列化協議各自具有特點,適用於不同場景:

1、公司之間系統呼叫,效能要求100ms,基於XML的SOAP協議是一個值得考慮的方案。

2、基於Web browser的Ajax,以及移動app與服務端之間的通訊,JSON是首選。對於效能要求不高或者以動態型別語言為主,傳輸資料小的場景,JSON是非常不錯的選擇。

3、對於除錯環境比較惡劣的場景,JSON或XML能夠極大的提高除錯效率,降低開發成本。

4、當對效能和簡潔性有極高要求的場景,可以考慮Protobuf、Thrift、Avro。

5、對於T級別的資料的持久化應用場景,Protobuf和Avro是首選。如果持久化後的資料儲存在Hadoop子專案裡,Avro是更好的選擇。

6、Avro的設計理念偏向於動態型別語言,對於動態語言為主的應用場景,Avro是更好的選擇。

7、持久層非Hadoop專案,以靜態型別語言為主的場景,Protobuf更符合開發習慣。

8、如果需要提供一個完整的RPC解決方案,Thrift是一個好的選擇。

9、如果序列化之後需要支援不同傳輸協議,或需要跨防火牆訪問,Protobuf可以優先考慮。

參考資料https://en.wikipedia.org/wiki/Serializationhttp://www.codeproject.com/Articles/604720/JSON-vs-XML-Some-hard-numbers-about-verbosityhttps://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarkinghttp://en.wikipedia.org/wiki/Serializationhttp://en.wikipedia.org/wiki/Soaphttp://en.wikipedia.org/wiki/XMLhttp://en.wikipedia.org/wiki/JSONhttp://avro.apache.org/http://www.oracle.com/technetwork/java/rmi-iiop-139743.htmlhttp://json.com/http://hessian.caucho.com/https://dubbo.apache.org/zh/docs/v2.7/user/references/protocol/hessian/https://en.wikipedia.org/wiki/Comparison_of_data-serialization_formatshttps://code.google.com/archive/p/thrift-protobuf-compare/wikis/Benchmarking.wiki

3
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 計算機視覺系統學習書籍/綜述(免費領)