微服務(wù)架構(gòu)之RPC-client序列化細(xì)節(jié)

微服務(wù)架構(gòu)之RPC-client序列化細(xì)節(jié)

第一章聊了【“為什么要進(jìn)行服務(wù)化,服務(wù)化究竟解決什么問題”

第二章聊了【“微服務(wù)的服務(wù)粒度選型”

上一篇聊了【“為什么說要搞定微服務(wù)架構(gòu),先搞定RPC框架?”

通過上篇文章的介紹,知道了要實施微服務(wù),首先要搞定RPC框架,RPC框架的職責(zé)要向【調(diào)用方】和【服務(wù)提供方】屏蔽各種復(fù)雜性:

(1)讓調(diào)用方感覺就像調(diào)用本地函數(shù)一樣

(2)讓服務(wù)提供方感覺就像實現(xiàn)一個本地函數(shù)一樣來實現(xiàn)服務(wù)

整個RPC框架又分為client部分與server部分:

RPC-client的部分流程如上圖,要進(jìn)行序列化反序列化(上圖中的1、4),要進(jìn)行發(fā)送字節(jié)流與接收字節(jié)流(上圖中的2、3)。

通過上一篇文章的用戶調(diào)研:

78%讀者 -> 繼續(xù)聊RPC框架技術(shù)細(xì)節(jié)

14%讀者 -> 聊微服務(wù)其他實踐

7%讀者 -> 不聊微服務(wù)了,聊最終一致性

那么按照多數(shù)讀者的意見,今天深入聊RPC的技術(shù)細(xì)節(jié),本文先討論RPC-client部分的【序列化反序列化】實施細(xì)節(jié)(筆者不是這方面的專家,有不對之處,歡迎大家指正,任何具有建設(shè)性意見的留言,將在下一章share給更多的小伙伴)。

一、為什么要進(jìn)行序列化

工程師通常使用“對象”來進(jìn)行數(shù)據(jù)的操縱:

class User{

std::Stringuser_name;

uint64_tuser_id;

uint32_tuser_age;

};

User u = new User(“shenjian”);

u.setUid(123);

u.setAge(35);

但當(dāng)需要對數(shù)據(jù)進(jìn)行存儲(固化存儲,緩存存儲)或者傳輸(跨進(jìn)程網(wǎng)絡(luò)傳輸)時,“對象”就不這么好用了,往往需要把數(shù)據(jù)轉(zhuǎn)化成連續(xù)空間的二進(jìn)制字節(jié)流,一些典型的場景是:

(1)數(shù)據(jù)庫索引的磁盤存儲:數(shù)據(jù)庫的索引在內(nèi)存里是b+樹或者h(yuǎn)ash的格式,但這個格式是不能夠直接存儲到磁盤上的,所以需要把b+樹或者h(yuǎn)ash轉(zhuǎn)化為連續(xù)空間的二進(jìn)制字節(jié)流,才能存儲到磁盤上

(2)緩存的KV存儲:redis/memcache是KV類型的緩存,緩存存儲的value必須是連續(xù)空間的二進(jìn)制字節(jié)流,而不能夠是User對象

(3)數(shù)據(jù)的網(wǎng)絡(luò)傳輸:socket發(fā)送的數(shù)據(jù)必須是連續(xù)空間的二進(jìn)制字節(jié)流,也不能是對象

所謂序列化(Serialization),就是將“對象”形態(tài)的數(shù)據(jù)轉(zhuǎn)化為“連續(xù)空間二進(jìn)制字節(jié)流”形態(tài)數(shù)據(jù)的過程,以方便存儲與傳輸。這個過程的逆過程叫做反序列化。

二、怎么進(jìn)行序列化

這是一個非常細(xì)節(jié)的問題,要是讓你來把“對象”轉(zhuǎn)化為字節(jié)流,你會怎么做?很容易想到的一個方法是xml(或者json)這類具有自描述特性的標(biāo)記性語言:

規(guī)定好轉(zhuǎn)換規(guī)則,發(fā)送方很容易把User類的一個對象序列化為xml,服務(wù)方收到xml二進(jìn)制流之后,也很容易將其范序列化為User對象(特別是語言支持反射的時候,就更easy了)。

第二個方法是自己實現(xiàn)二進(jìn)制協(xié)議來進(jìn)行序列化,還是以上面的User對象為例,可以設(shè)計一個這樣的通用協(xié)議:

(1)頭4個字節(jié)表示序號

(2)序號后面的4個字節(jié)表示key的長度m

(3)接下來的m個字節(jié)表示key的值

(4)接下來的4個字節(jié)表示value的長度n

(5)接下來的n個字節(jié)表示value的值

(6)像xml一樣遞歸下去,直到描述完整個對象

上面的User對象,用這個協(xié)議描述出來可能是這樣的:

(1)第一行:序號4個字節(jié)(設(shè)0表示類名),類名長度4個字節(jié)(長度為4),接下來4個字節(jié)是類名(”User”),共12字節(jié)

(2)第二行:序號4個字節(jié)(1表示第一個屬性),屬性長度4個字節(jié)(長度為9),接下來9個字節(jié)是屬性名(”user_name”),屬性值長度4個字節(jié)(長度為8),屬性值8個字節(jié)(值為”shenjian”),共29字節(jié)

(3)第三行:序號4個字節(jié)(2表示第二個屬性),屬性長度4個字節(jié)(長度為7),接下來7個字節(jié)是屬性名(”user_id”),屬性值長度4個字節(jié)(長度為8),屬性值8個字節(jié)(值為123),共27字節(jié)

(3)第四行:序號4個字節(jié)(3表示第三個屬性),屬性長度4個字節(jié)(長度為8),接下來8個字節(jié)是屬性名(”user_name”),屬性值長度4個字節(jié)(長度為4),屬性值4個字節(jié)(值為35),共24字節(jié)

整個二進(jìn)制字節(jié)流共12+29+27+24=92字節(jié)

實際的序列化協(xié)議要考慮的細(xì)節(jié)遠(yuǎn)比這個多,例如:強(qiáng)類型的語言不僅要還原屬性名,屬性值,還要還原屬性類型;復(fù)雜的對象不僅要考慮普通類型,還要考慮對象嵌套類型等。however,序列化的思路都是類似的。

三、序列化協(xié)議要考慮什么因素

不管使用成熟協(xié)議xml/json,還是自定義二進(jìn)制協(xié)議來序列化對象,序列化協(xié)議設(shè)計時要考慮哪些因素呢?

(1)解析效率:這個應(yīng)該是序列化協(xié)議應(yīng)該首要考慮的因素,像xml/json解析起來比較耗時,需要解析doom樹,二進(jìn)制自定義協(xié)議解析起來效率就很高

(2)壓縮率,傳輸有效性:同樣一個對象,xml/json傳輸起來有大量的xml標(biāo)簽,信息有效性低,二進(jìn)制自定義協(xié)議占用的空間相對來說就小多了

(3)擴(kuò)展性與兼容性:是否能夠方便的增加字段,增加字段后舊版客戶端是否需要強(qiáng)制升級,都是需要考慮的問題,xml/json和上面的二進(jìn)制協(xié)議都能夠方便的擴(kuò)展

(4)可讀性與可調(diào)試性:這個很好理解,xml/json的可讀性就比二進(jìn)制協(xié)議好很多

(5)跨語言:上面的兩個協(xié)議都是跨語言的,有些序列化協(xié)議是與開發(fā)語言緊密相關(guān)的,例如dubbo的序列化協(xié)議就只能支持Java的RPC調(diào)用

(6)通用性:xml/json非常通用,都有很好的第三方解析庫,各個語言解析起來都十分方便,上面自定義的二進(jìn)制協(xié)議雖然能夠跨語言,但每個語言都要寫一個簡易的協(xié)議客戶端

(7)歡迎大家補(bǔ)充…

四、業(yè)內(nèi)常見的序列化方式

(1)xml/json:解析效率,壓縮率都較差;擴(kuò)展性、可讀性、通用性較好

(2)thrift:沒有用過,歡迎大家補(bǔ)充

(3)protobuf:Google出品,必屬精品,各方面都不錯,強(qiáng)烈推薦,屬于二進(jìn)制協(xié)議,可讀性差了點,但也有類似的to-string協(xié)議幫助調(diào)試問題

(4)Avro:沒有用過,歡迎大家補(bǔ)充

(5)CORBA:沒有用過,歡迎大家補(bǔ)充

(6)mc_pack:懂的同學(xué)就懂,不懂的就不懂了,09年用過,傳說各方面都超越protobuf,懂行的同學(xué)可以說一下現(xiàn)狀

(7)…

五、后文預(yù)告

RPC-client的部分,除了要進(jìn)行序列化反序列化,還要進(jìn)行發(fā)送字節(jié)流與接收字節(jié)流,下一篇文章會介紹這一部分內(nèi)容。

RPC-client中數(shù)據(jù)的發(fā)送與接收遠(yuǎn)比序列化反序列化復(fù)雜,其涉及“連接池、負(fù)載均衡、故障轉(zhuǎn)移、隊列、超時、異步、上下文回調(diào)管理”等技術(shù),具體細(xì)節(jié),下篇再溝通。

==【完】==

回【sed】一分鐘sed入門(一分鐘系列)

回【廣告】一分鐘讀懂互聯(lián)網(wǎng)廣告競價策略(一分鐘系列)

回【陣列】一張“神圖”看懂單機(jī)/集群/熱備/磁盤陣列(一分鐘系列)

回【awk】一分鐘學(xué)awk夠用(一分鐘系列)

回【perl】十分鐘學(xué)perl夠用(一分鐘系列)

回【mongo】一分鐘了解mongodb(一分鐘系列)

回【2pc】一分鐘了解兩階段提交2PC(一分鐘系列)

回【join】30秒懂SQL中的join(一分鐘系列)

回【百度】百度咋做長文本去重(一分鐘系列)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,661評論 19 139
  • 轉(zhuǎn)自:http://blog.csdn.net/kesonyk/article/details/50924489 ...
    晴天哥_王志閱讀 25,346評論 2 38
  • 1. RPC 1.1 簡介 RPC 的主要功能目標(biāo)是讓構(gòu)建分布式計算(應(yīng)用)更容易,在提供強(qiáng)大的遠(yuǎn)程調(diào)用能力時不損...
    wy_sure閱讀 7,186評論 0 1
  • 這是一本很奇特的小書。翻看的那一刻,如進(jìn)入了一個人的內(nèi)心世界,這個人在窺探世界,我們看到了他窺探時記錄下的文字。當(dāng)...
    柳二白閱讀 1,261評論 0 6
  • 我多想在你想要結(jié)婚的年齡遇見你 并與你相愛 可我卻偏偏 在十開頭的年齡遇見了你 這般青蔥 怕不能成為陪你攜手一生的...
    落汲閱讀 291評論 0 1

友情鏈接更多精彩內(nèi)容