認識 Bond,Microsoft Bond - 一種新的數據序列化框架
已發表: 2022-03-11Microsoft Bond 是 Microsoft 創建的用於模式化數據的新序列化框架。
讓我們回顧一下數據序列化最常用的地方:
- 文件、流、NoSQL 和 BigData 中的數據持久性。
- 網絡、IPC等數據傳輸
通常,這些應用程序必須處理模式化數據,其中模式意味著:
- 結構:層次結構、關係、順序。
- 語義:自出生以來的年齡。
實際上,任何數據都有模式,即使它是由你的編程語言隱式定義或支持的。 當涉及到復雜的數據結構時,我們最終會編寫支持數據傳輸對象 (DTO) 和負責 IO 的代碼,通常使用不同的語言。 一旦它成長和發展,它很快就會成為維護所有這些部件的噩夢。 這就是序列化框架贏得比賽的地方。
首先,任何序列化框架都為數據模式定義定義了一個抽象,該抽像不受特定編程語言或平台的約束。 這種抽像被稱為 DSL(領域特定語言)。
有了這樣的 DSL,我們就可以為特定的應用程序定義數據模式。 反過來,定義可以用多種形式表示,但序列化框架通常支持一種非常適合其 DSL 的形式。 太複雜? 這是一個眾所周知的例子:XSD 和 XML。
XSD 定義了 DSL,XML 是(推薦)定義匹配 XSD 模式的文檔。 但是,您也可以使用“xsd.exe”生成與 XSD 匹配的 DTO 類,因此生成的類只是另一種形式。 請注意,您可以從 DTO 生成 XML,反之亦然,它們在語義上是相同的,因為語義是通用的:它是使用 XSD 定義的。 總而言之,序列化框架為您提供了一個 DSL,您可以使用它來以給定框架最支持的特定格式定義數據模式。
抽像數據模式最終將具體化為一組用編程語言表達的實體。 所有序列化框架都提供稱為代碼生成器的特殊工具。
它們為目標編程語言生成所有支持代碼,這是客戶端處理模式化數據所需的:DTO、代理等。這對於強類型語言是最終必需的,而對於鴨子類型(動態)語言來說是可選的.
最後但並非最不重要的問題是網絡上的數據持久性。 實際數據最終應序列化為原始字節(或文本)並反序列化。
所有數據序列化框架都提供了另一種抽象,稱為協議。 協議定義了一組規則,這些規則定義了結構化數據應如何根據其架構進行序列化或反序列化。 每個協議通常針對給定序列化框架支持的所有編程語言和平台實現。 它支持的編程語言/平台越多,它應該提供的實現就越多。
假設一個框架願意支持 JSON 協議,那麼它必須為 C#、C++、Windows、Linux 等提供 JSON 讀寫器。
綜上所述:任何現代數據序列化框架都為您提供以下內容:
- 抽象:DSL 和協議。
- 代碼生成工具。
- 協議實現。
Microsoft Bond 是一個現代數據序列化框架。 它提供強大的 DSL 和靈活的協議、C++ 和 C# 的代碼生成器,以及適用於 Windows、Linux 和 Mac OS X 的高效協議實現。
幾年來,Bond 一直是僅供內部使用的技術,但由於 Microsoft 開源計劃,Bond 已在 GitHub 上提供:Microsoft Bond。
數據序列化競爭對手
軟件巨頭之間的競爭導致了一系列序列化框架的出現:
- Google Inc. - Google 協議緩衝區
- Facebook Inc. - Thrift,現在由 Apache 維護
- Apache 基礎軟件 - Avro
顯然,它們都是不兼容的,這沒關係,除非您使用其中之一創建公共 API。
它們每個都有優點和缺點,因此您可以根據自己的需要從中進行選擇。
為什麼是邦德?
這個問題的官方答案在這裡:“為什麼是邦德”。
這是快速摘要:
- Bond 支持豐富的類型系統,包括泛型。
- Bond 支持模式版本控制和雙向兼容性。
- Bond 支持運行時模式操作。
- 邦德支持各種收藏:“矢量
, 地圖 , 列表 ”。 - Bond 支持類型安全的惰性序列化:“bonded
” - Bond 支持帶有編組和轉碼的可插拔協議(格式)
一個重要的注意事項是,邦德遵循“付費遊戲”策略。 您添加/使用的功能越多,您為尺寸和速度支付的費用就越多。 這為開發人員提供了極大的靈活性。
讓我們誠實地列出缺點:
- Bond 的目標是支持 C++ 和 C#,但不支持 Java(尚)的 Microsoft 堆棧。
- Bond 不支持聯合類型(protobuf 中的“oneof”)。
性能怎麼樣?
在將一個框架與另一個框架進行比較時,開發人員通常會尋找性能比較。 但讓我們回想一下,這些框架由 DSL、代碼生成器和協議組成。 如果您只考慮協議性能,那麼您將錯過 DSL 和 codegens 提供的功能。 有時,擁有更好的 DSL 比在序列化速度上有幾個百分點的差異更重要。
除了速度之外,某些協議支持的節省空間的編碼也很重要。 我鼓勵您與特定領域的數據進行性能/空間比較。 這是估計您可以從特定框架中獲得的所有好處的唯一方法。
本文附帶演示項目,該演示項目通過從 Windows 應用程序事件日誌中讀取所有記錄、將它們序列化為 Bond 對象並反序列化它們來演示 Bond 框架的使用。
要構建和運行演示,您無需安裝 Visual Studio 以外的任何軟件。
使用微軟債券
獲得債券
查看有關為您的平台獲取 Bond 的官方指南。
對於 .NET 項目,這很簡單:
install-package Bond.CSharp
套餐包括:
- bin 文件夾中的代碼生成器 (gbc.exe)
- .NET 庫
- MSBuild 任務
工作流程
工作流程包括以下步驟:
- 通過編寫“.bond”文件來學習 DSL 並定義數據模式。
- 使用代碼生成器(“gbc.exe”)為您的編程語言獲取 DTO。
- 在您的項目中引用生成的文件以及 Bond 運行時庫。
考慮使用框架提供的 MSBuild 任務來自動執行代碼生成步驟。
DSL 功能概述
當你開始編寫你的第一個“.bond”文件時,你需要知道它的語法和特性。 請訪問詳細描述 IDL 的官方文檔頁面。 讓我們回顧一下基本功能:
- 模塊:模式可以拆分為不同的文件,這些文件包含在“import”語句中。
- 命名空間:與 C++/C# 具有相同的含義。
- 用戶定義的結構:用戶類型定義的一個單元。
- 前向聲明對於遞歸數據結構很有用。
- 基本類型:“bool、uint8(到 64)、int8(到 64)、float、double、string、wstring”。
- 容器類型:“blob、list
, 向量 , 放 , map<K, T>, 可以為空 ”。 - 自定義類型的別名和映射,例如,如果您想在 C# 中使用“DateTime”,但在線上打勾(“int64”)。
- 自定義屬性:用於自定義代碼生成。
無聊的? 這是一個例子:
namespace MyProject struct MyRecord { 0: string Name = "Noname"; 1: vector<double> Constants; }
其中“0”和“1”是字段序數(可以是任意步長的任何整數), = "Noname"
是(可選)默認值。
代碼生成
Bond 框架提供了用 Haskell 編寫的代碼生成工具。 以下是如何在命令行中從“.bond”模式生成 C# 和 C++ 代碼:
gbc c# example.bond gbc c++ example.bond
支持的協議(格式)
開箱即用的 Bond 支持三種協議:
- 標記協議:“CompactBinary”和“FastBinary”
標記協議在有效負載中交錯模式元數據。 這使得有效負載具有自描述性,允許消費者在不知道生產者使用的模式的情況下對其進行解釋。
- 未標記的協議:“SimpleBinary”
無標籤協議僅序列化數據,因此要求消費者通過一些帶外機制了解有效負載模式。 未標記協議通常用於存儲場景,因為它們允許將模式存儲一次(例如,在數據庫的系統表中),從而消除了使用相同模式的許多記錄的元數據開銷。
- 基於 DOM 的協議:“SimpleJson”和“SimpleXml”
基於 DOM 的協議將整個有效負載解析為內存中的數據對像模型,然後在反序列化期間對其進行查詢。 通常,這種協議用於實現基於文本的編碼,例如 JSON 或 XML。
對於每個協議,Bond 運行時庫都為您提供了相應的 Reader 和 Writer 類,它們完成了實際序列化的工作。
使用協議非常簡單,比著名的“JsonConvert.SerializeObject()”稍微難一些:
var record = new MyRecord { Name = "FooBar", Constants = { 3.14, 6.28 } }; var output = new OutputBuffer(); var writer = new CompactBinaryWriter<OutputBuffer>(output); Serialize.To(writer, record); var input = new InputBuffer(output.Data); var reader = new CompactBinaryReader<InputBuffer>(input); record = Deserialize<Example>.From(reader);
下一步是什麼?
如果您喜歡 Bond,並且您有大量空閒時間進行編碼,請考慮將其中一項用於開發。 我不會列舉你可能從貢獻中獲得的所有好處,但我知道許多開發人員正在尋找可以貢獻的想法:
- 實現到 Java 的端口。 用您選擇的其他主流語言替換 Java。
- 實施 Bond 模式導入/導出以與其他 DSL 交換(例如“.proto <=> .bond”)。
無論您決定對 Bond 做什麼,我建議您先聯繫 Adam Sapek。 他是這個項目的負責人,他將指導您了解市場最需要的東西。