ProtoBuf 協(xié)議設計與開發(fā)

周日本來要去爬山的蜜宪,但是沒去成,突然想寫點東西圃验,但本人文采不好掉伏,只能閑扯一點技術(shù)方面的文章,整理了下有道筆記澳窑,然后最近一直在開發(fā)protobuf的協(xié)議接口斧散,就寫寫ProtoBuf相關(guān)的東西吧。

本文精髓:

? ?protobuf的消息設計

? ?消息分發(fā)設計Message Dispatch

? ?針對程序升級的proto設計

文章末尾對著三點做詳細說明摊聋。

?????最近一段時間在寫linux服務端接口程序鸡捐,剛開始如果按照需求的話,大概有十個接口左右麻裁,但是后面慢慢分解需求后,其實真正就只有五個接口煎源。

????編碼工作早早完成,進入到測試階段脚草,一般情況可能會等web實現(xiàn)完成后原献,然后借助web client,在做調(diào)試姑隅,但是這期間工作效率不高,而且存在很多問題慕趴,可能后臺接口沒實現(xiàn)好,也有可能web沒實現(xiàn)好冕房。作為linux后臺服務開發(fā),需要會模擬客戶單發(fā)送數(shù)據(jù)耙册,如果接口很簡單的話,可以直接使用telnet工具帝际。

????現(xiàn)在最為流行的后臺服務端通信的協(xié)議有:JSON饶辙、XML、ProtoBuf弃揽,當協(xié)議為這三種的時候,簡單的telnet就不能勝任了披粟,使用JSON和ProtoBuf的話咒锻,先借助工具做序列化工作,使用XML的話蒿辙,也要事先編寫好XML滨巴。

????為了更加高效的對后臺服務接口做好單元測試,也為了在web開發(fā)調(diào)試的時候恭取,提供穩(wěn)定的后臺服務接口,自己利用MFC寫了一個小的調(diào)試工具


參數(shù)設置里面輸入的是json串耗跛,因為這個有很多工具方便序列化攒发,如:https://www.bejson.com/jsoneditoronline/

????這個工具很簡單,從界面就三個輸入羔砾,IP、port姜凄、消息類型,主要工作就是模擬客戶端向服務端發(fā)送消息:

????????需要借用服務端的proto協(xié)議文件

????????序列化protobuf

????????根據(jù)消息類型做消息分發(fā)

????這里用到protobuf态秧,先大概說一下它的使用與原理

????1,介紹安裝

????????直接去百度空扎,這里就跳過

????2润讥,編寫 .proto文件

????????來個例子:

????????package lm;

????????message helloworld

????????{

????????required int32 ? ? id = 1; ?// ID

????????required string ? ?str = 2; ?// str

????????optional int32 ? ? opt = 3; ?//optional field

????????}

限定修飾符 + 數(shù)據(jù)類型 + 字段名稱 = 字段編碼值

盡量養(yǎng)成良好測編程習慣,對proto文件命名與消息名做規(guī)范的命名

????在上例中楚殿,package 名字叫做 lm,定義了一個消息 helloworld砌溺,該消息有三個成員变隔,類型為 int32 的 id规伐,另一個為類型為 string 的成員 str匣缘。opt 是一個可選的成員,即消息中可以不包含該成員培慌。

????3柑爸,編譯.proto文件

????寫好 proto 文件之后就可以用 Protobuf 編譯器將該文件編譯成目標語言了。本例中我們將使用 C++表鳍。假設您的 proto 文件存放在 $SRC_DIR 下面,您也想把生成的文件放在同一個目錄下进胯,則可以使用如下命令:

protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/addressbook.proto

命令將生成兩個文件:

????????lm.helloworld.pb.h , 定義了 C++ 類的頭文件

????????lm.helloworld.pb.cc 偎血, C++ 類的實現(xiàn)文件

????在生成的頭文件中,定義了一個 C++ 類 helloworld

????4颇玷,序列化

????在第三部編譯生成的cc文件中,有一系列的SerializeToXXX方法谒亦,如SerializeToArray空郊,可以根據(jù)具體情況用這一系列方法進行序列化份招。

????5狞甚,反序列化

????在第3個步驟編譯生成的cc文件中,有一系列的ParseFromXXX方法谐腰,如ParseFromArray涩盾,可以根據(jù)具體情況用這一系列方法進行反序列化。

????掌握以上幾個步驟基本就能搞定proto的開發(fā)了春霍,進階的話可以去掌握proto的數(shù)據(jù)類型以及requried、optional终畅、repeated限定修飾符竟闪,和message的嵌套(message嵌套可以設計出更多復雜的協(xié)議,滿足更復雜的需求)妖爷。

????protobuf的優(yōu)劣自己去百度理朋,JSON,XML我也有用過嗽上,但是相對來說,谷歌的protobuf是我用起來最方便高效的兽愤。

這是網(wǎng)上的一個測試結(jié)果:http://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking


????回到文章開頭部分說的精髓,現(xiàn)在逐一到來

????一逐沙,proto的設計:

????一般設計規(guī)則如下

????message Request

????{

????required fixed64 msgtype = 1;

????required bytes bodys = 2;

????}

????一個消息類型加一個消息體,但這不能滿足復雜的業(yè)務需求棚赔,所以復雜的系統(tǒng)里面一般拆成這樣:

????message Header

????{

????required fixed64 msgtype = 1;

????}

????message HelloworldRequest

????{

????required int32 ? ? id = 1; ?// ID

????required string ? ?str = 2; ?// str

????optional int32 ? ? opt = 3; ?//optional field

????}

????一個消息類型(單獨定義一個文件)對應一個請求消息徘郭,一個請求消息對應一個接口,消息里面的字段對應接口所需要的參數(shù)残揉,這是常用的設計方法,能滿足所有的業(yè)務需求冲甘。

????二,消息分發(fā)的設計

這里的message dispatch是指程序根據(jù)不同的msgtype濒憋,反序列化proto和做不同的業(yè)務邏輯處理陶夜。

????古老而又傳統(tǒng)的設計是采用switch case來做(我曾經(jīng)看到有在用if else的),這種方法有很多不足之處条辟,我這里舉幾個很常見的:

????1,代碼臃腫本姥,隨著消息類型的增加,會有n多的case

????2婚惫,假設case里漏掉了break魂爪;那就不妙了。

????3滓侍,代碼維護差,每次增加msgtype捺球,除了實現(xiàn)對應的業(yè)務邏輯處理街图,還要到消息入口增加對應的case懒构。

在c語言里面,有一種很實用的辦法絮姆,那就是函數(shù)指針秩霍,很多開源的和上層應用的回調(diào)函數(shù)或方法的底層都是封裝了c語言的函數(shù)指針,這里提到函數(shù)指針铃绒,我簡單介紹一下(本文沒有用很大篇幅來說明函數(shù)指針,掌握其基本定義颠悬,慢慢學會衍生到復雜的概念):

????????從概念上說,函數(shù)指針是指向函數(shù)的指針變量诞外,它本質(zhì)上是一個指針變量灾票。

????????其廣泛的定義是: int (*f) (int x);

????????復制和調(diào)用: int func(int x); ? f = func;

????那么函數(shù)指針在Message Dispath 如何設計呢,還是來一個簡單的例子:

????定義一個結(jié)構(gòu)體

????????struct SMsgCmd {

????????int msgtype; ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*msg type*/

????????int (*func)(const char *argv); ? ? ? ? ? /* handler * 函數(shù)指針/

????????};

????定義一個結(jié)構(gòu)體數(shù)組刊苍,并初始化

????????static struct SMsgCmd commands[] = {

????????{ 1, ? Request1},

????????{ 2, ? Request1},

????????};

????在服務程序的消息入口處,遍歷改數(shù)組即可

????????for ()

????????{

????????if (msgtype == commands[i].msgtype){

????????(*commands[i].func)(argv);

????????}

????????}

在c++11里面啥纸,可以利用std::function?和std::bind埠忘,其原理跟函數(shù)指針一個道理。

????三莹妒,針對程序升級的proto設計

????程序升級是常有的事绰上,但我們升級的時候需要考慮兼容性,之前有看到過同個版本號如

????if (version == 1){

????}

????else if (version > 2)

????.........

????這樣做的缺陷我就不在過多的說明了鉴腻。

????對于proto的協(xié)議來說迷扇,我們只要做到以下幾點爽哎,就會完美兼容新舊版本

1,不要隨意添加或刪除 required限定詞修飾的字段

????????2厨内,不要隨意改變現(xiàn)有字段編碼值

????????3渺贤,若需要新增字段,請用optional限定詞修飾

本文到此就算結(jié)束了志鞍,若有錯誤之處,請多多指教固棚!

歡迎關(guān)注本人微信公眾號:lzyTalk江湖,不只是談江湖唆缴,還會分享很多技術(shù)干貨哦黍翎!


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市趟紊,隨后出現(xiàn)的幾起案子碰酝,更是在濱河造成了極大的恐慌,老刑警劉巖送爸,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異墨吓,居然都是意外死亡,警方通過查閱死者的電腦和手機帖烘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門橄杨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來照卦,“玉大人乡摹,你說我怎么就攤上這事〈狭” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵图云,是天一觀的道長邻邮。 經(jīng)常有香客問我,道長筒严,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任摹恨,我火速辦了婚禮娶视,結(jié)果婚禮上晒哄,老公的妹妹穿的比我還像新娘肪获。我一直安慰自己,他們只是感情好较木,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布青柄。 她就那樣靜靜地躺著,像睡著了一般致开。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上喇喉,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天拣技,我揣著相機與錄音千诬,去河邊找鬼膏斤。 笑死,一個胖子當著我的面吹牛傲茄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播盘榨,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蟆融,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了型酥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤郁竟,失蹤者是張志新(化名)和其女友劉穎由境,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體虏杰,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年攻询,在試婚紗的時候發(fā)現(xiàn)自己被綠了州弟。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡拯杠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出潭陪,到底是詐尸還是另有隱情,我是刑警寧澤依溯,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站枝秤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏淀弹。R本人自食惡果不足惜庆械,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望缭乘。 院中可真熱鬧,春花似錦忿峻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽到逊。三九已至滤钱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間件缸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工争剿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留痊末,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓凿叠,卻偏偏與公主長得像嚼吞,于是被迫代替她去往敵國和親蹬碧。 傳聞我的和親對象是個殘疾皇子舱禽,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 由于工程項目中擬采用一種簡便高效的數(shù)據(jù)交換格式呢蔫,百度了一下發(fā)現(xiàn)除了采用 xml飒筑、JSON 還有 ProtoBuf(...
    黃海佳閱讀 48,640評論 1 23
  • 轉(zhuǎn)自:http://blog.csdn.net/kesonyk/article/details/50924489 ...
    晴天哥_王志閱讀 24,810評論 2 38
  • 我們身處的藍色星球绽昏,不過是浩瀚宇宙中的一粒塵埃。每個你愛過的人全谤、每個你聽說過的人、每個曾經(jīng)存在過的人认然,都在...
    炫彩和音閱讀 367評論 0 0
  • 在一個開心的中午毕骡,因為喵喵家好久沒有那么熱鬧了削饵,喵喵想:“一家人都在未巫,真好”。 那天叙凡,喵喵的媽媽在洗衣...
    星同百分百閱讀 204評論 0 0
  • 摘錄有一個缺點,即使整段的摘錄文章跛璧,在少了上文鋪墊的情況下都會對理解文章中的寓意大打折扣。不過現(xiàn)在大家的生活節(jié)奏都...
    王赫麟閱讀 592評論 0 0