DDS问与答

整理一些DDS以及DDS-XRCE上的一些思考

DDS Specification

Q&A

  • Q:DDS位与网络栈的那一层
  • A:传输层之上,基于TCP、UDP
  • Q:DDS全局数据空间到底在哪里?
  • A:事实上DDS的全局数据空间并不存在于物理界的某个确定位置,而是一种抽象的概念。事实上是通过DDS发送消息,更新了远程节点上的存储。其本质就是所有DDS中各个应用程序的本地空间的集合。任何系统运行的所有语言的任何应用程序都会以最佳的符合自己格式的方式读取到数据,正是因为数据存在于自己的内存空间。
  • Q:我从ROS1出发,了解到ROS1的发布订阅是这个样子的:发布者-Master-订阅者,发布者和订阅者通过topic进行对应,该关系是在master节点上的。然后在ROS2中,了解到它使用了去中心化,不要一个单独的Master来维持关系,而是使用DDS进行负责底层消息的传递。那么我就很好奇DDS是如何来做这一步的?DDS有一个所谓的global data domain全局数据空间,但它又一再强调,这个全局数据空间仅仅存在于概念上,那么对于该空间内的所有节点,他们是怎么知道和彼此之间的订阅关系呢?是否代表他们每个节点都要存储网络内所有其他参与者的信息呢?DDS中间件又存在于哪里呢?如果是DDS中间件在控制这个GDD,他们怎么解决同步关系呢?他们是存在于总线上么?(感觉不太可能)
  • A:

DDSI-RTPS

DDS specification和DDSI-RTPS的关系

两者都是DDS规范,前者定义了上层模型,也就是DCPS(以数据为中心的发布-订阅模型),后者通过UDP传输实现best-effort和realiable的通信,主要目的是实现互操作性。他们在结构上应该是有一种上层和底层的关系。

pub-sub和RTPS.JPG

DDS-XRCE

DDS-XRCE不是一个类似于DDS的发布订阅机制的通讯协议。而是一个让嵌入式设备端的Client通过DDS域内的一个Agent,通过重用一些DDSI-XRCE协议和DDS Specification中定义的功能,来实现Client在DDS域中发送、订阅消息的功能。

DDS-XRCE的通信协议——我的理解

DDS-XRCE通信协议.png

在一个DDS-XRCE协议中,定义了以上这些概念。

Session是client和agent进行通信的双向链接,是通过一次握手建立的。

stream是独立信息流,管理一批message,是依托于session的

message就是一个信息,由一个messageHeader和一群submessage组成,属于某个stream,message header中,信息由sessionId和streamId标识,每条message在流内有序,由sequenceNr指定流内顺序,

clientKey是一个标识,仅仅在0-127号stream(best-effort流)中存在。其目的是为了在best-effort这种情况下使Agent迅速知道message对应来自于哪个client。而在128-256号stream(reliable流)中之所以不存在,则是因为代理已经拥有预制了client的clientKey,不需要确认每条消息是否来自于某个client。(问:如何知道的呢?猜想:应该是在stream建立时就确认了client的clientkey,所以只需要sessionId和streamId就可以确认client)

submessage是最直接的具体消息的载体,由submessageHeader和payload组成,前者包括了submessageId来标识submessage的种类(一共有13种),flag来定义内容相关,比如大小端序、以及submessageLength来告知整个submessage的长度。后者就是具体的某种submessage所包括的信息。

想象两个城市隔海相望,为了互通有无,两者互相通了气之后,挖了一个隧道,取名叫Session,然后为了合理运用这个隧道,对隧道进行了分层,比如上层跑车队下层跑地铁,这就是不同的stream。无论哪一种交通工具中,都有一个车头(MessageHeader),车头标注了它是来自于哪个城市(clientKey)、属于哪一个隧道(session)、哪一层(stream),在所有车次中属于哪一车次(sequenceNr)的信息。车头后面跟的就是车厢或者其他跟着车头跑的车(submessage),为了方便统计,这些车厢或者车同样有一个自己的身份证(submessageHeader),包括了他们的类型(submessageId)、负载方式(flags)以及负重(submessageLength),最后当然最重要的是每个车厢和车子都有自己的负载(payload)。

XRCE-DDS

Q:CREATE_CLIENT消息是否每次client沉睡唤醒后都需要调用?如果是的话Agent是否知道何时为创建何时为重用?如果不是的话client唤醒后如何发送消息?

A:根据specification的介绍,当create_client操作被触发进行执行时,检索agent端是否存在和client_key对应的ProxyClient,如果存在,则比较ProxyClient的session_id和传入的参数的信息,如果都相同,则不做任何操作,只是将返回状态置为STATUS_OK,否则就需要删除原来的ProxyClient,创建新的ProxyClient,这样导致的后果是之前所有和该proxyClient所绑定的对象全都失效。从这里来看,理论上讲没有必要再每次client沉睡唤醒后都调用。只需要从client端已经存在来的TrasportLocator,来执行和Agent交流的行为就可以了。

Q:CREATE消息创建Object对象时,是否规定了object_id,如果规定了object_id,这个取值从何而来,如何保证全局唯一性?

A:不全是,CREATE操作实际上输入的是objectid_prefix,它是组成objectid的元素而非objectid,它和object_kind共同组成objectid来保证其唯一性,生成的真正的objectid会以create函数的返回值的形式,利用STATUS信息返回给Client。

如何保证唯一性,事实上CREATE的输入还有一个creationMode参数,这个参数有两个布尔值作为成员变量,一个是reuse,一个是replace,再加上构成的objectid,这三者共同决定了是创建object、还是使用object、还是删除已存在的object创建新的object。

Q:XRCE Cookie起到了什么作用?和普通的http连接中的cookie的作用是相同的么?

A:在一般的http通信中,cookie存储在客户端,在会话过程中可以起到对客户端进行标识,让服务端session知道客户端的功能。在XRCE-DDS中,主要用于区分Client的是clientkey这一子消息。所以cookie应当与http中所用的cookie技术不同。鉴于specification中描述,似乎XRCE-DDS中的XRCE-Cookie被锁定为‘X’、‘R’、‘C‘、’E‘,所以估计它的作用主要是用来进行区分协议。