DDS服务发现

概述

DDS的服务发现协议,让网络中(同一个domain)的节点能够相互发现。有了服务发现机制,各个应用能够快速发现远程的新加入的节点,同时也能将自己告知其他节点。
DDS服务发现分为两个部分:

  • Participant Discovery Protocol (PDP)
    PDP用于Participant 之间的相互发现
  • Endpoint Discovery Protocol (EDP)
    EDP用于Endpoint(一个reader或者writer都是一个Endpoint)之间的相互发现

根据DDS的规范,各协议栈可以实现自己定义的PDP和EDP,但是,都必须实现Simple Participant Discovery Protocol (SPDP)和Simple Endpoint Discovery Protocol (SEDP)
DDS的服务发现还分为静态服务发现和动态服务发现。
其中静态服务发现只用SPDP,而动态服务发现会用到SPDP和SEDP

  • 本文会结合fastdds官方用例HelloWorldExample和StaticHelloWorldExample的网络报包来进行说明(网络包地址:https://blog.youkuaiyun.com/ouyang035/article/details/147978578)。
  • wireshark过滤器
    ((ip.src198.18.7.22 && (ip.dst198.18.7.101||ip.dst239.255.0.1))|| (ip.src198.18.7.101 && (ip.dst198.18.7.22||ip.dst239.255.0.1)))&&!ssh&&!tcp

预制模块

SPDP和SEDP主要是通过build-in endpoint和build-in topic来进行通信,从而实现信息的交换,完成相互发现。

  • build-in endpoint
    SPDPbuiltinParticipantWriter
    SPDPbuiltinParticipantReader
    SEDPbuiltinPublicationsWriter
    SEDPbuiltinPublicationsReader
    SEDPbuiltinSubscriptionWriter
    SEDPbuiltinSubscriptionReader
    SEDPbuiltinTopicsWriter(抓包中未出该消息)
    SEDPbuiltinTopicsReader(抓包中未出该消息)
    BuiltinParticipantMessageReader
    BuiltinParticipantMessageWriter
  • build-in topic
    有四个预定义的Topic:
    DCPSParticipant
    DCPSPublication
    DCPSSubscription
    DCPSTopic(抓包中未出该消息)

在这里插入图片描述BuiltinParticipantMessageReader和BuiltinParticipantMessageWriter是实现writer liveliness机制所需要的。每一个participant都可以通过设置使能/禁止wirter liveness机制,相应的使能或禁止这两个endpoint。

pqos.wire_protocol().builtin.use_WriterLivelinessProtocol = false // fastdds 默认是true

SPDP

PDP的目的是发现网络上其他的participant的存在及其属性。
SPDPbuiltinParticipantWriter是一个RTPS 的Best-Effort StatelessWriter。它会定期像预配置地locators列表发送SPDPdiscoveredParticipantData,通常来说是往组播地址(默认239.255.0.1)发送。它的HistoryCache包含一个SPDPdiscoveredParticipantData类型的数据对象,这个数据对象的内容是由participant的属性信息确定(例如,domain id, participant支持什么EDP协议, 单播和组播地址和端口)。
SPDPdiscoveredParticipantData的属性
在这里插入图片描述
在这里插入图片描述

SPDPbuiltinParticipantReader的HistoryCache中包含了所有活跃的participants的信息,key用来识别每个不同的participant(通过participant GUID)。
每当SPDPbuiltinParticipantReader接收到关于participant的信息时,SPDP会检查HistoryCache,寻找一个与participant GUID匹配的key的内容。如果没有找到匹配的key的条目,就会以参与者的GUID为key添加新的条目。
SPDP会周期性检查SPDPbuiltinParticipantReader的historycache,寻找旧的条目,这些条目被定义为那些超过leaseDuration没有收到消息的条目。然后删除它们。

availableBuiltinEndpoints提供了预制endpoints的信息(参考下面第三张图片)。包括
PUBLICATIONS_DETECTOR(SPDPbuiltinParticipantReader)
PUBLICATIONS_ANNOUNCER(SPDPbuiltinParticipantWriter)
SUBSCRIPTIONS_DETECTOR(SEDPbuiltinSubscriptionReader)
SUBSCRIPTIONS_ANNOUNCER(SEDPbuiltinSubscriptionWriter)
TOPICS_DETECTOR(SEDPbuiltinTopicsReader)
TOPICS_ANNOUNCER(SEDPbuiltinTopicsWriter)
PARTICIPANT_MESSAGE_READER(BuiltinParticipantMessageReader)
PARTICIPANT_MESSAGE_WRITER(BuiltinParticipantMessageWriter)

红框内都是SPDP消息
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

SEDP

SEDP协议的目标是Participant间能发现彼此的writer和reader。
用于SEDP的built-in Entities的QoS设置成reliable

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上图是DDSHelloWorldExample_first_pub.cap的消息流
其中2个蓝色方框内的是SEDP消息
红色线条标识的是A的publication信息发给B的过程
绿色色线条标识的是B的subscription信息发给A的过程
但是在第一个框框内,HelloWorldTopic相关的reader和writer就完成了匹配。
A的publication发给B的具体流程如下(红色线条):

  • A的SEDPbuiltinPublicationsWriter发送heartbeat给B的SEDPbuiltinPublicationsReader,告知它的history cache中有sample1(firstAvaliableSeqNumber为1,lastSeqNumber为1,所以最新的sample的sequence number为1)
    在这里插入图片描述
  • B收到heartbeat,解析后发现A最新的change是sample1,它没有收到过sample 1,所以发送acknack 告知丢失了sample1(bitmapBase=1, numBits=1, 表示sample 1丢失)
    在这里插入图片描述
  • A发送sample1给B,告知它有一个针对HelloWorldTopic的publisher, 到这一步后,A的publisher信息已经发送给到了B。
    由于A已经得到了B的subscriber消息,所以A user_writer就可以开始往B发送心跳了。
    在这里插入图片描述
  • A发送heartbeat, 告知最新的change为sample1
    在这里插入图片描述
  • B发送acknack,告知期望sample2(bitmapBase=2, numBits=0, 表示sample 2丢失0次,那就是说收到的最新的heartbeat的change为sample1, 收到的最新的data也是sample1。 也就是expecting example2)
    在这里插入图片描述
    B的subscription发送给B的具体流程如下(绿色线条):
  • B的SEDPbuiltinSubscriptionWriter发送heartbeat给A的SEDPbuiltinSubscriptionReader,告知它的history cache中有sample1(firstAvaliableSeqNumber为1,lastSeqNumber为1,所以最新的sample的sequence number为1)
    在这里插入图片描述
  • A收到heartbeat,解析后发现B最新的change是sample1,它没有收到过sample 1,所以发送acknack 告知丢失了sample1(bitmapBase=1, numBits=1, 表示sample 1丢失)
    在这里插入图片描述
  • B发送sample1给A,告知它有一个针对HelloWorldTopic的subscriber
    在这里插入图片描述
  • B发送heartbeat, 告知最新的change为sample1
    在这里插入图片描述
  • A发送acknack,告知期望sample2(bitmapBase=2, numBits=0, 表示sample 2丢失0次,那就是说收到的最新的heartbeat的change为sample1, 收到的最新的data也是sample1。 也就是expecting example2)
    在这里插入图片描述
  • 由于B只有一个用户定义的reader,至此,B的subscription发现流程完成。
    在这里插入图片描述

Liveness

BuiltinParticipantMessageWriter发送的心跳消息如下。(其作用暂时不清楚)
在这里插入图片描述
#静态发现
采用静态服务发现的话,SPDP过程是一样的,但是不需要SEDP过程了,取而代之的是通过在xml文件来配置对端的节点信息。

  • publisher
    pqos.name("HelloWorldPublisher");
    pqos.wire_protocol().builtin.discovery_config.use_SIMPLE_EndpointDiscoveryProtocol = false;
    pqos.wire_protocol().builtin.discovery_config.use_STATIC_EndpointDiscoveryProtocol = true;
    pqos.wire_protocol().builtin.discovery_config.static_edp_xml_config("file://HelloWorldSubscriber_static_disc.xml");
    participant_ = DomainParticipantFactory::get_instance()->create_participant(0, pqos);

发送方需要用到配置的接收方的信息如下HelloWorldSubscriber_static_disc.xml

<staticdiscovery>
	<participant>
		<name>HelloWorldSubscriber</name>
		<reader>
			<userId>3</userId>
			<entityId>4</entityId>
            <topicName>HelloWorldTopic</topicName>
			<topicDataType>HelloWorld</topicDataType>
			<topicKind>NO_KEY</topicKind>
			<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>
		</reader>
	</participant>
</staticdiscovery>

运行

./DDSStaticHelloWorldExample publisher
  • subscriber
    pqos.name("HelloWorldSubscriber");
    pqos.wire_protocol().builtin.discovery_config.use_SIMPLE_EndpointDiscoveryProtocol = false;
    pqos.wire_protocol().builtin.discovery_config.use_STATIC_EndpointDiscoveryProtocol = true;
    pqos.wire_protocol().builtin.discovery_config.static_edp_xml_config("file://HelloWorldPublisher_static_disc.xml");
    participant_ = DomainParticipantFactory::get_instance()->create_participant(0, pqos);

发送方需要用到配置的接收方的信息如下HelloWorldPublisher_static_disc.xml

<staticdiscovery>
	<participant>
		<name>HelloWorldPublisher</name>
		<writer>
			<userId>1</userId>
			<entityId>2</entityId>
            <topicName>HelloWorldTopic</topicName>
			<topicDataType>HelloWorld</topicDataType>
			<topicKind>NO_KEY</topicKind>
			<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>
		</writer>
	</participant>
</staticdiscovery>

运行

./DDSStaticHelloWorldExample subscriber

wireshark抓包分析没能看到,没有SEDP消息了
在这里插入图片描述

参考文档

https://zhuanlan.zhihu.com/p/12663878689

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值