【轉】GOOGLE-PROTOBUF與FLATBUFFERS數據的序列化和反序列化

轉載自【黑米GameDev街區】 原文連接: http://www.himigame.com/unity3d-game/1607.htmlhtml

 

 關於Protobuf 經過本文的轉載和分享的相關連接,足夠了解使用了,因此這裏不贅述了。可是這裏Himi順便提一下「FlatBuffers」 ,它是 Protocol Buffers升級版,其主要區別在於FlatBuffers在訪問數據前不須要解析/拆包這一步。android

           這裏分享一個FlatBuffers 的連接,童鞋們也能夠去了解下 http://itindex.net/detail/50777-google-flatbuffers-%E5%BC%80%E6%BA%90 .編程

          最後再多說一句,從同事(以前騰訊的)那裏瞭解到,騰訊也有一套相似的框架 TSF4G,很牛x,據說FlatBuffers 這種就是參考的TSF4G作的。固然這裏也放出參考連接,有興趣的也能夠去了解下:http://djt.qq.com/article/view/298     http://zqted.com/qq-mmog-share-learn.html網絡

 

【如下內容,均爲轉載】數據結構

★protobuf是啥玩意兒?
爲了照顧從沒據說過的同窗,照例先來掃盲一把。
首先,protobuf是一個開源 項目(官方站點在「這裏 」),並且是後臺很硬的開源項目。網上現有的大部分(至少80%)開源項目,要麼是某人單幹、要麼是幾個閒雜人等合夥搞。而protobuf則否則,它是鼎鼎大名的Google公司開發出來,而且在Google內部久經考驗的一個東東。因而可知,它的做者絕非通常閒雜人等可比。
那這個聽起來牛X的東東到底有啥用處捏?簡單地說,這個東東干的事兒其實和XML 差很少,也就是把某種數據結構的信息,以某種格式保存起來。主要用於數據存儲、傳輸協議格式等場合。有同窗可能心理犯嘀咕了:放着好好的XML不用,幹嗎從新發明輪子啊?!先別急,後面俺天然會有說道。
話說到了去年(大約是08年7月),Google忽然大發慈悲,把這個好東西貢獻給了開源社區。這下,像俺這種喜歡撿現成的傢伙可就有福啦!貌似喜歡撿現成的傢伙還蠻多滴,再加上 Google的號召力,開源後不到一年,protobuf的人氣就已經很旺了。因此俺爲了與時俱進,就單獨開個帖子來忽悠一把。框架

★protobuf有啥特點?
掃盲完了以後,就該聊一下技術 方面的話題了。因爲這玩意兒發佈的時間較短(未滿週歲),因此俺接觸的時間也不長。今天在此是先學現賣,列位看官多多包涵能好/效率高socket

如今,俺就來講說Google公司爲啥放着好端端的XML不用,非要另起爐竈,從新造輪子。一個根本的緣由是XML性能不夠好。
先說時間開銷:XML格式化(序列化)的開銷倒還好;可是XML解析(反序列化)的開銷就不敢恭維啦。俺以前常常碰到一些時間性能很敏感的場合,因爲不堪忍受XML解析的速度,棄之如敝履。
再來看空間開銷:熟悉XML語法的同窗應該知道,XML格式爲了有較好的可讀性,引入了一些冗餘的文本信息。因此空間開銷也不是太好(不過這點缺點,俺不常碰到)。
因爲Google公司賴以吹噓的就是它的海量數據和海量處理能力。對於幾十萬、上百萬機器的集羣,動不動就是PB級的數據量,哪怕性能稍微提升 0.1% 也是至關可觀滴。因此Google天然沒法容忍XML在性能上的明顯缺點。再加上Google歷來就不缺造輪子的牛人,因此protobuf也就應運而生了。
Google對於性能的偏執,那但是出了名的。因此,俺對於Google搞出來protobuf是很是滴放心,性能上不敢說是最好,但確定不會太差。編程語言

◇代碼 生成機制
除了性能好,代碼生成機制是主要吸引俺的地方。爲了說明這個代碼生成機制,俺舉個例子。
好比有個電子商務的系統(假設用C++實現),其中的模塊A須要發送大量的訂單信息給模塊B,通信的方式使用socket。
假設訂單包括以下屬性:
--------------------------------
時間:time(用整數表示)
客戶id:userid(用整數表示)
交易金額:price(用浮點數表示)
交易的描述:desc(用字符串表示)
--------------------------------
若是使用protobuf實現,首先要寫一個proto文件(不妨叫Order.proto),在該文件中添加一個名爲」Order」的message結構,用來描述通信協議中的結構化數據。該文件的內容大體以下:分佈式

--------------------------------工具

message Order
{
required int32 time = 1;
required int32 userid = 2;
required float price = 3;
optional string desc = 4;
}

--------------------------------
而後,使用protobuf內置的編譯器編譯 該proto。因爲本例子的模塊是C++,你能夠經過protobuf編譯器的命令行參數(看「這裏 」),讓它生成C++語言的「訂單包裝類」。(通常來講,一個message結構會生成一個包裝類)
而後你使用相似下面的代碼來序列化/解析該訂單包裝類:
--------------------------------

// 發送方

Order order;
order.set_time(XXXX);
order.set_userid(123);
order.set_price(100.0f);
order.set_desc(「a test order」);

string sOrder;
order.SerailzeToString(&sOrder);

// 而後調用某種socket的通信庫把序列化以後的字符串發送出去
// ……

--------------------------------

// 接收方

string sOrder;
// 先經過網絡通信庫接收到數據,存放到某字符串sOrder
// ……

Order order;
if(order.ParseFromString(sOrder))  // 解析該字符串
{
cout << 「userid:」 << order.userid() << endl
<< 「desc:」 << order.desc() << endl;
}
else
{
cerr << 「parse error!」 << endl;
}

--------------------------------
有了這種代碼生成機制,開發人員不再用吭哧吭哧地編寫那些協議解析的代碼了(幹這種活是典型的吃力不討好)。
萬一未來需求發生變動,要求給訂單再增長一個「狀態」的屬性,那隻須要在Order.proto文件中增長一行代碼。對於發送方(模塊A),只要增長一行設置狀態的代碼;對於接收方(模塊B)只要增長一行讀取狀態的代碼。哇塞,簡直過輕鬆了!
另外,若是通信雙方使用不一樣的編程語言來實現,使用這種機制能夠有效確保兩邊的模塊對於協議的處理是一致的。
順便跑題一下。
從某種意義上講,能夠把proto文件當作是描述通信協議的規格說明書(或者叫接口規範)。這種伎倆其實老早就有了,搞過微軟的COM編程或者接觸過CORBA的同窗,應該都能從中看到IDL(詳細解釋看「這裏 」)的影子。它們的思想是相通滴。

◇支持「向後兼容」和「向前兼容」
仍是拿剛纔的例子來講事兒。爲了敘述方便,俺把增長了「狀態」屬性的訂單協議成爲「新版本」;以前的叫「老版本」。
所謂的「向後兼容」(backward compatible),就是說,當模塊B升級了以後,它可以正確識別模塊A發出的老版本的協議。因爲老版本沒有「狀態」這個屬性,在擴充協議時,能夠考慮把「狀態」屬性設置成非必填 的,或者給「狀態」屬性設置一個缺省值(如何設置缺省值,參見「這裏 」)。
所謂的「向前兼容」(forward compatible),就是說,當模塊A升級了以後,模塊B可以正常識別模塊A發出的新版本的協議。這時候,新增長的「狀態」屬性會被忽略。
「向後兼容」和「向前兼容」有啥用捏?俺舉個例子:當你維護一個很龐大的分佈式系統時,因爲你沒法同時 升級全部 模塊,爲了保證在升級過程當中,整個系統可以儘量不受影響,就須要儘可能保證通信協議的「向後兼容」或「向前兼容」。

◇支持多種編程語言
俺開博以來點評 的幾個開源項目(好比「Sqlite 」、「cURL 」),都是支持不少種 編程語言滴,此次的protobuf也不例外。在Google官方發佈的源代碼中包含了C++、Java 、Python三種語言(正好也是俺最經常使用的三種,真爽)。若是你平時用的就是這三種語言之一,那就好辦了。
假如你想把protobuf用於其它語言,咋辦捏?因爲Google一呼百應的號召力,開源社區對protobuf響應踊躍,近期冒出不少其它編程語言的版本(好比ActionScript、C#、Lisp、Erlang、Perl、PHP 、Ruby等),有些語言還同時搞出了多個開源的項目。具體細節能夠參見「這裏 」。
不過俺有義務提醒一下在座的各位同窗。若是你考慮把protobuf用於上述這些語言,必定認真評估對應的開源庫。由於這些開源庫不是Google官方提供的、並且出來的時間還不長。因此,它們的質量、性能等方面可能還有欠缺。

★protobuf有啥缺陷?
前幾天剛剛在「光環效應 」的帖子裏強調了「要同時評估優勢和缺點」。因此俺最後再來批判一下這玩意兒的缺點。
◇應用 不夠廣
因爲protobuf剛公佈沒多久,相比XML而言,protobuf還屬於初出茅廬。所以,在知名度、應用廣度等方面都遠不如XML。因爲這個緣由,假如你設計的系統須要提供若干對外的接口給第三方系統調用,俺奉勸你暫時不要考慮protobuf格式。
◇二進制格式致使可讀性差
爲了提升性能,protobuf採用了二進制格式進行編碼。這直接致使了可讀性差的問題(嚴格地說,是沒有可讀性)。雖然protobuf提供了TextFormat這個工具類(文檔在「這裏 」),但終究沒法完全解決此問題。
可讀性差的危害,俺再來舉個例子。好比通信雙方若是出現問題,極易致使扯皮(都不認可本身有問題,都說是對方的錯)。俺對付扯皮的一個簡單方法 就是直接抓包並dump成log,能比較容易地看出錯誤在哪一方。可是protobuf的二進制格式,致使你抓包並直接dump出來的log難以看懂。
◇缺少自描述
通常來講,XML是自描述的,而protobuf格式則不是。給你一段二進制格式的協議內容,若是不配合相應的proto文件,那簡直就像天書通常。
因爲「缺少自描述」,再加上「二進制格式致使可讀性差」。因此在配置文件方面,protobuf是確定沒法取代XML的地位滴。

★爲何俺會用上protobuf?
俺自從前段時間接觸了protobuf以後,就着手把俺負責的產品中的部分數據傳輸協議替換成protobuf。可能有同窗會問,和protobuf相似的東東也有很多,爲啥獨獨相中protobuf捏?因爲今天寫的篇幅已經蠻長了,俺賣個關子,把這個話題留到「生產者/消費者模式[5]:如何選擇傳輸協議及格式?」。俺會在後續的這個帖子裏對比各類五花八門的協議格式,並談談俺的淺見。

 

1.GoogleProtoBuf開發者指南  http://wenku.baidu.com/link?url=IlqKZ0Uc-NVs1KmGlQBw6IoRf6UTIln8QBEhtZ-5qWwAm6xcGYF3z6nMzaIDb-wA9R2ULnqh4XbXpFGXx6rqdKb41h8B_hxGWe0vYlp9-0W

2.  .protobuf文件轉成.cs文件方法      http://www.cnblogs.com/pctzhang/archive/2012/08/30/2663804.html

3. lua下使用protobuf   http://www.thinksaas.cn/group/topic/276365/

4. android與PC,C#與Java 利用protobuf 進行無障礙通信【Socket】   http://www.cnblogs.com/TerryBlog/archive/2011/04/23/2025654.html

5. protobuf 小示例 http://www.cnblogs.com/sifenkesi/p/4045392.html

相關文章
相關標籤/搜索