认识 Bond,Microsoft Bond - 一种新的数据序列化框架

已发表: 2022-03-11

Microsoft 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。 他是这个项目的负责人,他将指导您了解市场最需要的东西。