ProtoBuf 初次見面

什麼是ProtoBuf?

這是一個Google所開發出的資料儲存結構或物件(反)序列的結構(如 JOSN、XML、msgpack等),在官方網站的介紹上有這麼一段:

Protocol buffers are Google’s language-neutral,
platform-neutral, extensible mechanism for serializing structured data
– think XML, but smaller, faster, and simpler.
You define how you want your data to be structured once,
then you can use special generated source code to easily write
and read your structured data to and from a variety of data streams and using a variety of languages.

from https://developers.google.com/protocol-buffers/

ProtoBuf支援各種主流的語言(ex: C#, C++, JAVA等),
在官方中的GitHub上有目前支援的語言實做,或是Third-party搜尋相關的實做套件。

ProtoBuf 優點

  • (反)序列速度快,方便於網路傳輸
  • 產出格式內容小,方便存放至檔案或其他Service

ProtoBuf 缺點

  • 二進位格式,難以閱讀
  • 使用上必須先作定義,需要先設定.proto檔案

在 C# 中使用 ProtoBuf

在專案中我是使用third-party的套件,ProtoBuf-net
套件可以在nuget上找到,會選擇這個套件主要是因為在使用上較為簡便,也支援較多的設定的方式來做資料,設定的方式
稍後會有比較詳細一些的介紹。

ProtoBuf-net
ProtoBuf-net

定義方式

ProtoBuf-net設定的方式支援了以下三種方式

Attribute

這個方式,個人認為是一個較好的設定方式,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[ProtoContract]
public class TestClass
{
[ProtoMember(1)]
public int TestA { get; set; }
[ProtoMember(2)]
public string TestB { get; set; }
[ProtoMember(3)]
public TestClassB TestC { get; set; }
}
[ProtoContract]
public class TestClassB
{
...
}

這一個設定方式可以修改data model同時修改 Attribute 這樣在團隊使用上可以避免修改data model後
也可馬上維護protobuf的設定,避免在runtime時因為設定上造成exception。

.proto檔案

這一個方式是官方的標準設定,這個需要額外產生一份.proto檔案,定義方式與格式可參考
官方網站
的設定。

這一個方式因為多產生了一個.proto的檔案,在修改data model後,必須要再額外修改.proto的檔案,
有時候在開發上會有不一致的情況;在使用上與設定上也相對較為複雜。

Runtime 定義

這是在Application執行期間產生一份 RuntimeTypeModel,在Serializer的時候會以這一份RuntimeTypeModel為你的
data model做序列化,以下提供語法參考設定方式

這一個方式會將原先定義覆蓋

1
2
3
4
var metaType = RuntimeTypeModel.Default.Add(typeof(TestClassA), true);
metaType.AddSubType(100, typeof(TestA));
RuntimeTypeModel.Default.Add(typeof(TestA), false);

這一個會複寫(或新增)原先的定義

1
2
3
4
var metaType = RuntimeTypeModel.Default;
var testA = metaType[typeof(TestClassA)];
testA.AddSubType(100, typeof(TestA));
metaType.Add(typeof(TestA), false);

總結

目前會採用ProtoBuf序列化是因為先前使用JSON有效能上的問題與在存取Redis上產生較高的延遲,所以改採用
ProtoBuf來作為資料序列化與存放到Redis的主要格式。雖然在閱讀上需要自己寫小工具做轉譯,但在一般情況
擁有較好的效能展現。

其他更詳細的介紹可觀看
protobuf-net 官方GitHub

參考資料

Level up - protobuf-net - Serialize/DeSerialize data

protobuf-net 官方GitHub

Google protobuf