大型分散式C++框架《三:序列化與反序列化》
原貼:http://www.cnblogs.com/ztteng/p/5381096.html
一、前言
個人感覺序列化簡單來說就是按一定規則組包。反序列化就是按組包時的規則來接包。正常來說。序列化不會很難。不會很複雜。因為過於複雜的序列化協議會導致較長的解析時間,這可能會使得序列化和反序列化階段成為整個系統的瓶頸。就像壓縮檔案、解壓檔案,會佔用大量cpu時間。
所以正常的序列化會在時間和空間上考慮。個人感覺對於電商業務時間應該是相對重要些。畢竟使用者沒有那麼多時間等你解析。 我們是用thrift來序列化的。一份thrift檔案生成2份。一份是c++生成的用來編寫服務介面。一份是php生成的。所有請求都會先落到前端機器。然後前端機器用php呼叫服務端函式介面。返回處理結果。這其實是遠端呼叫rpc。
二、分配序列化空間的大小
說序列化之前先說下平臺給序列化分配的buf的空間大小
1、每個協程會分配大概固定包頭(56個位元組)+特殊buf(200個位元組)的空間來儲存包頭。所以首先如果收到的包特殊buf(就是放sessionkey和uid等資訊)大於200個位元組。會報錯不處理。但是並不會給netio 返回一個錯誤包訊息。所以客戶端 會一直等到客戶端設定的超時時間 2、每個container會分配3M的空間來處理資料。所以去掉包頭和特殊buf.剩下的就是可以用來序列化的空間3*1024*1024-固定包頭-特殊buf。 所以最少會有 3*1024*1024-56-200的空間 這裡其實可以看到協程的好處。這個3M的空間。對於每個協程來說是共享的。因為我們是協程的方式,其實是一種順序流程,沒有協程會跟你競爭使用這個buf的資源。因為可以自己手動控制協程的切換。三、序列化步驟
1、我們先看下請求。
oCntlInfo.setOperatorUin(10458); oCntlInfo.setOperatorKey("abcde"); oCntlInfo.setRouteKey(1234); std::string source = "aaaaa"; std::string inReserve; std::string errmsg; std::string outStr; std::string machineKey; for(int i =0;i<500*1024;i++) { machineKey.append("a"); } AoActionInfo oActionInfo; oActionInfo.SetDisShopId(1111); oActionInfo.SetDistributorId(2222); uint32_t dwResult = Stub4App.AddActionSupplier( oCntlInfo, machineKey, source, 1, 1, oActionInfo, inReserve, errmsg, outStr); if(dwResult == 0) { std::cout << "Invoke OK!" << std::endl; std::cout << "Invoke OK!" << std::endl; }
客戶端直接呼叫函式介面。到服務端請求結果
最後需要序列化的東西如下是類_Cao_action_AddActionSupplier_Req函式的入參都是我們需要序列化的內容。注意這裡是rpc呼叫的一個關鍵點。
2、序列化開始
a) 先看下我們的thritf
如果下圖。發現我們的函式入參也是打上了tag標誌的。作用跟我們在結構體中打tag標誌是一樣的。為了標識一個欄位的含義。
序列化的時候把這些tag序列化進去。 然後反序列化的時候靠這些tag來解析
b ) 先把圖貼出來。按著圖來講更清晰些
c) 首先我們會建立一個CByteStream的類來。序列化內容。在CByteStream的建構函式會自動寫入一個位元組的序列化包頭。值為1
CByteStream(
char
* pStreamBuf = NULL, uint32_t nBufLen = 0,
bool
bStore=
true
,
bool
bRealWrite =
true
);
pStreamBuf 是序列化buf指標 pStreamBuf 是序列化的長度 bStore true表示是否需要包資料儲存下來。 false表示不需要把資料存下來 bRealWrite 表示是否支援讀寫buf d) 接著就開始寫類_Cao_action_AddActionSupplier_Req的成員變數。其實就是函式入參。寫的時候是先協tag就是下圖中的fid。 其實就是在thrift中已經寫好的函式入參的tag值。 具體寫的過程我們先看簡單基本型別。比如strMachineKey 1)先寫tag。 strMachineKey 的tag為1. 程式裡規定tag佔兩個位元組。所以函式入參可以是0xffff個。 2 ) 接著會寫4個固定的位元組。用來儲存後面緊跟著資料的值。這裡strMachineKey的長度是512000. 3 ) 寫內容 。 把strMachineKey的內容寫入緊跟著的buf 針對整形和長整形就不說了 大同小異 e) 接著我們關注下 是怎麼寫結構體oActionInfo的。 1)先寫tag。 oActionInfo 的tag為5. 程式裡規定tag佔兩個位元組。 2 ) 接著針對結構體這裡 會寫4個固定的位元組用來存結構體序列化長度。因為開始不知道所以值為0。 3 ) 接著寫欄位DistributorId。 它在oActionInfo結構體中的tag值為6.型別為int64. 所以先寫tag=6佔兩個位元組,接著分配4個位元組存長度。最後分配8個位元組存內容 4)跟著寫DisShopId欄位。就不細說了 5)最後寫了2個位元組包尾 6)最後 回寫結構體的長度 這裡注意下寫結構體時候的寫法。不注意的話會看錯。 1)這裡先拿到開始寫結構體的buf指標。注意這裡是用的int32_t。佔四個位元組。跟前面保持一直。這裡用來的存後面總序列虛化結構體提的總長度。 2)由於剛開始的時候 並不知道後面的結構體會序列化多少個位元組。所以這裡先寫4個位元組。 同時把這便宜的4個位元組的記憶體值 設定為0 bs<<0; (這裡其實建議寫成 bs<<int32_t(0) 會好一點。開起來一致) 這裡開始沒注意。以為寫4個位元組值為0的 結構體的頭。其實這裡是放結構體長度的 3)最後第5步。 重新賦值 結構體的長度
1)int32_t* pLen = (int32_t*)bs.getRawBufCur(); 2)bs << 0; 3)int32_t iLen=bs.getWrittenLength(); 4)Serialize_w(bs); 5)*pLen = bs.getWrittenLength() - iLen;
f)最後對整個_Cao_action_AddActionSupplier_Req寫了兩個位元組的包尾
g) 我麼可以看到oActionInfo其實有一堆的欄位。但是我們在請求的時候只寫了兩個欄位。所有在序列化的時候也只序列化了兩個欄位其實我們可以看到我們的這種序列化,很整齊。很規則。比較緊湊。但是並不節省空間。這個裡面有很多資料可以壓縮的。但是壓縮帶來一個問題就是解壓的時候很消耗cpu的。跟我的業務場景不服和。也沒必要。
四、序列化解析
其實知道了資料是怎麼寫入的 解析起來就很容易了。其實這種序列化就是兩邊約定規則。知道規則以後就可以解析了
解析的具體步驟就不詳細說了。這裡說下解析的時候幾個特殊的地方
五、話外
我們的這一套就是遠端呼叫rpc服務。通過我們的序列化。
其實就能瞭解所謂的RPC服務是什麼樣的。
說白了,遠端呼叫就是將物件名、函式名、引數等傳遞給遠端伺服器,伺服器將處理結果返回給客戶端。
為了能解析出這些資訊。在入參的時候做上標識(這裡是打tag).
谷歌的protobuf也用過。跟thrift其實差不多但是序列化和反序列的話的具體實現是有些不同的。
谷歌的protobuf更節省空間
以前具體看過序列化的原始碼。覺得序列化反序列化以及rpc很神祕。現在看了原始碼才發現確實寫的確實好,
但是沒那麼神祕裡。其實就是按一定規則組包。所以還是要多看原始碼啊。
我們用的thrift就是 facebook的thrift。但是改了些東西。大體是一樣的。
相關推薦
大型分散式C++框架《三:序列化與反序列化》
原貼:http://www.cnblogs.com/ztteng/p/5381096.html 一、前言 個人感覺序列化簡單來說就是按一定規則組包。反序列化就是按組包時的規則來接包。正常來說。序列化不會很難。不會很複雜。因為過於複雜的序列化協議會導致較
大型分散式C++框架《一:框架簡介》
下面簡單介紹下情況。框架是騰訊電商平臺的分散式框架。雖然騰訊拍拍已經玩完了。但是這套框架還是很不錯的。而且據原騰訊同事說微信也是用的這套框架。原始碼肯定是不能說的。但是介紹大體的思想我想應該沒問題。雖然在這個框架下寫了一年多的業務程式碼。但是平臺框架的程式碼一直沒怎麼看。最近有開始看平臺程式碼雖然沒看完。
Java序列化與反序列化三連問:是什麼?為什麼要?如何做?
Java序列化與反序列化是什麼? Java序列化是指把Java物件轉換為位元組序列的過程,而Java反序列化是指把位元組序列恢復為Java物件的過程: 序列化:物件序列化的最主要的用處就是在傳遞和儲存物件的時候,保證物件的完整性和可傳遞性。序列化是把物件轉換成有序位元組流,以便在網路上傳輸或者儲存在本地檔
C#對象序列化與反序列化
space ros 個人信息 瀏覽器 特性 點名 文件名 屬性節點 派生 1.對象序列化的介紹 (1).NET支持對象序列化的幾種方式 二進制序列化:對象序列化之後是二進制形式的,通過BinaryFormatter類來實現的,這個類位於System.Runtime.Seri
C#語言-08.序列化與反序列化
clas 本質 cnblogs 語法 信息 字段 使用 serializa col a. 序列化:是將對象的狀態存儲到特定存儲介質中的過程 i. 語法:public void Serialize(序列化過程的文件流,保存的對象)
如何使用 JSON for Modern C++ 序列化與反序列號,換行符導致序列化失敗
http gb2 elf ldp c++ spi ssp 使用 b16 W48z士5742i4鍁鉀http://shequ.docin.com/qbvl66336 6j夠裝何掖tj嘔蔡5VLhttp://tushu.docin.com/olybb166 渤k搶97L巳綱鋅7
【轉】C# 序列化與反序列化
使用 ria tle 輸入 == 必須 mls zab ddr 轉自:https://www.cnblogs.com/lsy131479/p/8371858.html 對象持久化到文本文件,策略是:將對象的屬性值打散,拆解,分別存儲。 序列化: 保存對象的"全景圖" 序
C#序列化與反序列化
color bsp private start sys bin create body null 一、序列化: 1 public void SerilizeData() 2 { 3 FileStream fs =
C# 使用 protobuf 進行對象序列化與反序列化
member 開源項目 serial all 序列化與反序列化 ace ogl serialize dll protobuf 是 google的一個開源項目,可用於以下兩種用途: (1)數據的存儲(序列化和反序列化),類似於xml、json等; (2)制作網絡通信協議。
C#使用JavaScriptSerializer類實現序列化與反序列化得到JSON
JavaScriptSerializer類由非同步通訊層內部使用,用於序列化和反序列化在瀏覽器和Web伺服器之間傳遞的資料。 1、新增引用 專案新增:System.Web.Extensions.dll的引用; 程式碼新增:using System.Web.Script.Serializa
c# 通過json.net中的JsonConverter進行自定義序列化與反序列化
iter 希望 生成 ade json.net .json implement else col 相信大家在工作中會經常遇見對json進行序列化與反序列化吧,但通常的序列化與反序列化中的json結構與c#中的類模型結構是相對應的,我們是否可以在序列化一個對象時候,讓我們
Fastjson:Java高效能JSON庫,序列化與反序列化
Fastjson是一個Java語言編寫的高效能功能完善的JSON庫。它採用一種“假定有序快速匹配”的演算法,把JSON Parse的效能提升到極致,是目前Java語言中最快的JSON庫。Fastjson介面簡單易用,已經被廣泛使用在快取序列化、協議互動、Web輸出、And
c# 序列化與反序列化
序列化又稱序列化,是.NET執行時環境用來支援使用者定義型別的流化的機制。其目的是以某種儲存形成使自定義物件持久化,或者將這種物件從一個地方傳輸到另一個地方。 .NET框架提供了兩種序列化的方式:1、是使用BinaryFormatter進行序列化;2、使用SoapF
Atitit rpc之道 attilax著 艾龍 著 1. 遠端過程呼叫協議 2 2. RPC需要解決的問題: 組成部分 3 2.1. 通訊問題 : 3 2.2. 序列化 與 反序列化 : 3 2
Atitit rpc之道 attilax著 艾龍 著 3. 歷史 4 遠端過程呼叫協議 編輯 同義詞 RPC一般指遠端
分散式系統中的序列化與反序列化
1.定義以及相關概念 作者 劉丁 釋出於 2015年5月7日 | 3 討論 分享到: 微博 微信 Facebook Twitter 有道雲筆記 郵件分享 稍後閱讀我的閱讀清單 簡介 文章作者服務於美團推薦與個性化組,該組致力於為美團使用者提供每天bi
分散式基礎之序列化與反序列化
目錄 序列化與反序列化,Why? 序列化的意義 一個簡單例項 JAVA序列化的高階認識 serialVersionUID 的作用 靜態變數序列化 父類的序列化 Transient 關鍵字 序列化的儲存規則 序列化實現深克隆 常見
【轉】c#--json序列化與反序列化
原文連結http://blog.csdn.net/gf771115/article/details/27114257 建立類 public class Person { private string name; public st
Unity與C#的序列化與反序列化
序列化操作在我們的開發中使用的十分普遍,本文記錄了公司最近分享會上關於這部分的講解,希望能幫助大家對序列化有更系統的瞭解。 概念 序列化又稱序列化,是.NET執行時環境用來支援使用者定義型別的流化的機制。其目的是以某種儲存形式使自定義物件持久化,或者將這種物件從一個地方傳輸到另一個地方。
C# JSON字串序列化與反序列化
using System.Runtime.Serialization.Json; using System.Runtime.Serialization; 二、C#將物件序列化成JSON字串 publicstring GetJsonString() { List<Product>
C#序列化與反序列化以及深拷貝淺拷貝
基於二進位制資料流的序列化和反序列化 /// <summary> /// 序列化 /// </summary> /// <typeparam name="T"></typeparam>