DDS通信中间件——XTypes规范

DDS通信中间件——XTypes规范

做了十年DDS通信中间件产品的程序员和大家分享一下对DDS这套规范的个人理解。预期本系列文章将包括以下内容陆续更新:

  1. DDS规范概述
  2. DCPS规范解读 & QoS策略
  3. DDS-XTypes规范解读
  4. RTPS规范解读
  5. DDS安全规范解读
  6. DDS-RPC规范解读
  7. DDS-TSN规范解读
  8. DDS-XRCE规范解读

1. 概述

问:为什么DDS规范要定义这么复杂的一个类型规范?

答:这个问题可以在DDS规范概述里面的1.3.1章节中找到答案,因为DDS主题需关联某个特定的数据类型,并具备以下这些能力使得DDS表现的像能够理解业务数据一样。

  • 自定义类型相关的发送/接收接口,即提交给DDS和从DDS中获取的是主题关联的自定义数据结构对象。
    • 优势
      • 序列化/反序列化的工作从应用下沉到中间件,由中间件考虑端序/对齐/不同语言类型的转换;
      • 类型检查,在编译期即可检查出部分问题;
    • 劣势
      • 使用复杂,即便是简单的收发也需要IDL编译器编译支持代码;
  • 数据筛选,DDS提供类似于数据库的实时数据存储与查询的功能,包括:
    • 将主题数据按照key值组织,比如订阅端可以仅读取特定key值的数据;
    • 内容过滤,即订阅端可以配置只关心某个成员范围之间的值,DDS将自动过滤不属于这个范围的主题数据;
  • 类型规范是不同DDS产品互联互通的基础
    • 产品遵循相同的规范使得能够支持的数据类型互认;
    • 数据样本序列化方式规范使得A厂家的DDS产品序列化的数据可以由B厂家的DDS产品反序列化还原成相同类型的样本数据;

以数据为中心是DDS与其他消息中间件的一个重要的区别。DDS-XTypes是实现以数据为中心的核心协议。最新版本的DDS-XTypes规范是2020年发布的V1.3版本,大家可以在这个页面找到DDS-XTypes协议及其附件。DDS-XTypes规范的主要内容参见下图,主要内容包括:

  • 类型系统,支持的数据类型及其语法规则,更进一步的描述了类型如何演进;
  • 类型描述,采用何种格式来描述数据类型;
  • 数据序列化, 采用什么方式序列化数据类型实例;
  • 语言绑定,如何映射为特定的开发语言;
  • DDS相关扩展,描述该规范与DCPS规范如何关联并扩展DCPS规范。
DDS-XTypes协议大纲

2. 类型系统

2.1. 类型描述

类型描述定义开发语言无关的各种类型的语言以及结构,具体包含的类型参见上图,协议中规定DDS主题能够关联的数据类型只包括:结构体struct以及联合体union,其他类型则作为这两种聚合类型的成员。

除了常规的类型/成员定义外,类型系统中还为类型或者成员添加了一些标签来提供额外的信息,常见的几个标签参见下表。

标签 作用对象 说明
Extensibility 类型 用于表明该类型的可扩展性,详见2.2.
Nested 类型 是否直接关联到DDS主题
key 成员 表明成员是否为键值
optional 成员 表明成员是否为可选
id 成员 指定成员的唯一ID
bound string/sequence/map成员 表明变长结构的长度上界,主要用于空间管理

2.2. 类型演进

DDS可扩展性分为3种,详见下表,为什么取名叫“类型演进”,因为基于APPENDABLE/MUTABLE可扩展性类型,原有系统无需做任何的代码、配置的修改,即可与新的系统(使用迭代后的新的数据类型)进行数据交互。

可扩展性 说明
FINAL 不可扩展,类型结构必须完全一致才能相互交换数据,用于保护已有系统。
APPENDABLE 可追加,这种类型是默认的类型,新的类型是基于老的类型在后面添加成员得到,这种模式下新老数据结构关联的主题能够相互交换数据。
MUTABLE 可随意变换,新的类型可将老的类型重新排序组合以及添加新的成员得到,这种模式下新老数据结构关联的主题能够相互交换数据。
FINAL可扩展性示例

上图中下面蓝色部分代表已有运行系统,上面的橙色部分代表新建的系统,新建的发布/订阅应用将位置信息从原有的2个坐标修改为3个坐标,此时由于原有系统设置为FINAL的保护状态,新的应用无法集成到老的系统中去。

APPENDABLE可扩展性示例

上图中下面蓝色部分代表已有运行系统,上面的橙色部分代表新建的系统,新建的发布/订阅应用将位置信息从原有的2个坐标修改为3个坐标,此时由于类型系统设置为APPENDABLE可扩展状态,老的应用不修改任何的配置以及代码,即可把新的发布/订阅应用集成到原有的系统中,老的订阅者(右下)将接收到新的发布者发布的数据,其中多出的z成员将被忽略,而新的订阅者应用(左上)将接收到老的发布端者发布的数据,其中缺少的z成员将赋予默认的值。

MUTABLE可扩展性示例

上图中下面蓝色部分代表已有运行系统,上面的橙色部分代表新建的系统,新建的发布/订阅应用将位置信息将原有的x、y坐标打乱并在中间插入一个新的成员z,此时由于类型系统设置为MUTABLE可扩展状态,老的应用不修改任何的配置以及代码,即可把新的发布/订阅应用集成到原有的系统中,老的订阅者(右下)将接收到新的发布者发布的数据,其中多出的z成员将被忽略,而新的订阅者应用(左上)将接收到老的发布端者发布的数据,其中缺少的z成员将赋予默认的值。

介绍到这里可能会产生一个疑问:既然能够支持MUTABLE类型,那所有的类型都设计成可变的类型,系统的可扩展性不就可以得到保证吗,为什么还需要支持前面两个类型?答案总结在下面的这张不同类型的优劣势中,不同类型可扩展性实现的关键技术在数据序列化中介绍。

可扩展性 优势 劣势
FINAL 1、首先是安全,类似于Java里面把一个类声明为final禁止其他类型继承扩展;2、固定结构下数据序列化/反序列化效率高 无可扩展性
MUTABLE 具备很好的可扩展性 结构可变带来底层序列化/反序列化需要携带更多的额外信息,导致效率变低
APPENDABLE 1、具备一定的可扩展性;2、接近于固定结构序列化/反序列化效率高 可扩展性有限

3. 类型描述

类型描述很好理解,就是选用一种载体把类型系统中定义出来的类型表达出来,这种表达可以有很多种:

  • 文本模式,人类友好的表达模式

    • IDL描述,这时一种平台(语言、处理器、操作系统)无关的描述方式,说起来高大上起始就是自定义了一套类C的语法规格来描述类型,IDL本身是平台无关的,那么必然还需要配套的IDL到不同开发语言/平台的映射规范,这些都是参考已有的OMG Corba规范的内容,本质上不属于OMG DDS规范;
    • 当所有系统仅涉及某一个平台或者开发语言时,可以直接采用相应的开发语言来描述,比如:使用C结构体定义;
    • XML/JSON描述,采用常用的文本描述语言来描述结构;
  • 二进制模式,机器友好的表达模式,无需进行文本处理即可遍历获得数据结构的信息

    • TypeObject二进制结构;
    • 早期版本RTI公司NDDS的TypeCode结构;
类型描述示例

3.1. IDL编译器

DDS需要负责自定义数据类型的序列化以及反序列化过程,那么这个过程必然涉及到对自定义数据结构的遍历,再针对每个成员进行特定的序列化/反序列化操作,这个过程需要一个工具来自动化实现,这个工具我们把它叫做编译器,针对不同类型描述方式会需要多种编译器,例如:IDL编译器、XML编译器,主要是第一阶段功能不同,后面的阶段需针对不同的开发语言、平台生成平台相关的支持文件,详细参见下表。

DDS编译器功能架构
分类 说明
样本生命周期管理 创建、初始化、回收、拷贝自定义数据对象(样本)
序列化/反序列化 将自定义对象序列化为RTPS子消息元素(二进制透明报文)、从RTPS报文中反序列化构造自定义对象
二进制类型描述 遍历二进制结构构造协议规定的TypeObject对象供底层使用
类型相关的接口 自动生成自定义类型相关的数据发送(DataWriter::write)、接收(DataWriter::read/take系列)接口

4. 数据序列化

4.1. PLAIN_CDR

PLAIN_CDR是本协议提供的一种二进制序列化算法,仅序列化数据内容,具备较高的空间使用效率,数据结构在自动发现阶段通过内置数据中的TypeObject对象交换一次。PLAIN_CDR是FINAL以及APPENDABLE类型的默认序列化方式,其算法要点如下:

  • 基本数据类型:直接拷贝对应的字节大小到对应的序列化地址空间
    • 注意地址对齐(对齐大小=被序列化的类型大小);
    • 注意大小端转换,当本机端序与要求的端序不同时,需要先转换端序再拷贝;
  • string/sequence/map等变长成员:先序列化4字节长度信息,再依次序列化元素;
  • 结构体:依次序列化成员,深度优先;
PLAIN_CDR示例

上图为CDRExample自定义类型的对象object的序列化实例,其中二进制为序列化后结果,下面为对应的成员或者对齐,上面为其对应的值,可以看到s成员进行了2字节对齐,i成员进行了4字节对齐,str成员携带了字符串长度0。

4.2. PARAMETERIZED CDR

PARAMETERIZED CDR是本协议提供的另一种二进制序列化算法,它将样本序列化为一个Parameter(参数)列表,其中每个参数由参数头和参数体构成,其中参数头包括部分成员信息,比如成员的编号(ID)、属性(是否为key/optional等),参数体包含成员的具体值,可以看到Parameterized CDR相对于PLAIN_CDR而言对每个成员都额外添加了一个参数头,带来的好处是:无需按照严格的定义顺序序列化,也可以添加或者删除成员,坏处在于序列化的效率降低了,该类型可用于实现MUTABLE可扩展性方式。

PARAMETERIZED CDR示例

4.3. XML序列化

XML序列化是本协议提供的一种文本序列化算法,具备较低的空间使用效率,主要包含如下消耗:

  • 每个样本中都包含完整的成员信息;
  • 文本在某些场景下具备较低的封装效率,例如封装值为10000000的整型,需要8个字节,而二进制实际仅需4个字节;
XML序列化示例

4.4. 性能对比

CDR和比较流行的其他序列化库的对比:Google ProtoBuf、Apache Thrift性能对比,这个课题比较复杂,在互联网上只搜索到eProsima的一篇技术文章,但是现在打不开了,后续有时间再全面进行对比。

5. 语言绑定

这个章节定义了两种使用自定义数据类型的方式:

  • 静态:常见的方式,通过IDL等方式描述自定义数据类型,通过DDS编译器生成支撑文件,将生成的文件与业务代码进行联编,这种方式比较繁杂并且修改类型时需要替换支撑文件并重编。
  • 动态:通过本规范提供的DynamicTypeBuilder以及DynamicTypeData相关的API接口通过代码构造类型,并使用动态通用序列化/反序列化、生命周期管理等方法,这块内容较为零散,这里不展开分析,有兴趣的可以私信讨论。

6. DDS扩展

这一章主要提一下用户用DDS时并不是必须使用IDL自定义数据类型,本协议为DDS提供了一些常用的内置数据类型,包括:

  • 字符串;
  • 带key的字符串;
  • 透明缓冲区;
  • 带key的透明缓冲区;

当用户能够自己管理序列化以及反序列化时,可以跳过自定义数据结构的过程,直接使用内置的数据类型进行开发,简化整个开发的流程。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,809评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,189评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,290评论 0 359
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,399评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,425评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,116评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,710评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,629评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,155评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,261评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,399评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,068评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,758评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,252评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,381评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,747评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,402评论 2 358

推荐阅读更多精彩内容