查看原文
其他

技术文档丨Cyber RT拓扑发现介绍

阿波君 Apollo开发者社区 2022-07-29



拓扑结构是指网络中各个站点相互连接的形式,在局域网中明确一点讲就是文件服务器、工作站和电缆等的连接形式。网络的拓扑结构反映出网络中各实体的结构关系,是建设计算机网络的第一步,是实现各种网络协议的基础,它对网络的性能,系统的可靠性与通信费用都有重大影响。


在P2P网络通信中,我们需要解决的两个首要问题就是——和谁进行通信以及如何进行通信。不管通信方式是选择TCP还是UDP,我们都需要获取对端的一些标识,如IP和端口号等,从而建立连接。


本次将介绍第一点的解决方式:参与者的标识和参与者的互相发现。




  以下,ENJOY  




在Cyber RT中,我们将主要通信角色(Role)分为:


  1. Node。

  2. Reader/Writer。

  3. Server/Client。

 

每个角色使用RoleAttributes进行标识。其中,Reader/Writer以及Server/Client都是在Node中创建的,Reader和Writer可以通过Channel进行三种方式的通信,Server通过Service向Client提供服务。因此,Cyber RT中的拓扑就是指各通信角色的位置、发布/订阅等信息。

 

我们可以通过使用有向图来抽象整个系统中的角色和它们之间的关系。其中,Reader/Writer和Server/Client可以用图的顶点表示,Node则在逻辑上对这四种角色进行包含。图的边我们用Channel表示,Channel从Writer流向Reader,表示Writer/Reader的发布/订阅关系。实际上,Server和Client也是通过Channel进行通信的。这在Cyber RT中被称为系统的拓扑(Topology)结构。赋予各个角色以唯一标识,并使用Channel同其它系统中的角色进行通信,这就是拓扑发现。


因此,拓扑发现主要用来获取整个系统中各个角色的分布:


  1. 整个系统创建的Node,以及这些Node创建的Writer/Reader/Server/Client。

  2. 使用某个Channel进行通信的Writer/Reader。

  3. 和某个Service相关联的Server/Client。




拓扑发现主要有两种方式:

 

  1. 静态拓扑发现。在配置文件中事先指定各Writer/Reader和Channel等的对应关系。该方法的优点是拓扑发现迅速,缺点则是配置缺少灵活性。

  2. 动态拓扑发现。


动态拓扑发现又分为以下两种:


  1. 中心化的拓扑发现。启动一个名字发现服务作为中心点,当创建Node等角色时,向这个服务进行注册,并获取已有的所有角色信息,同时,Server需要向已有的注册节点发送更新消息。这种方式容易出现单点问题,并且由于长连接的建立,会导致系统资源的负载增大。

  2. 去中心化的拓扑发现。采用广播或者组播的方式,向系统中的其它参与者报告本角色的加入/退出。这种方式解决了单点问题,同时减少了连接量,但是当节点同时加入时,容易产生广播风暴。

 

综合考虑,Cyber RT使用动态的去中心化拓扑发现,采用第三方eProsima Fast RTPS进行通信管理。使用该库的组播接口,通过设置CYBER_DOMAIN_ID(可以转换成整形的字符串)来建立一个DOMAIN,不同DOMAIN之间的通信不会互相干扰。我们可以利用该特性,通过设置不同的Domain ID,来在同一台机器中运行多套Cyber RT系统。

 



Cyber RT创建了以下几个拓扑管理者:


  1. NodeManager:主要用来管理和查询整个系统中的Node。

  2. ChannelManager:主要管理和查询Channel相关的拓扑,涉及到Node/Writer/Reader。我们可以从中获取到一个Channel的所有Writer/Reader,可以根据一个Channel是否有相应的Reader来判断对端是否已经初始化完成,以准备发送数据等。

  3. ServiceManager:主要用来管理和查询整个系统中的Server和Client。


其中:


  1. NodeManager和ServiceManager中节点存储比较简单,使用Role-ID和RoleAttributes映射的map存储即可。

  2. ChannelManger包含了Channel相关的Node/Writer/Reader的存储。可以用来查询Node创建以及和Channel有关的所有Writer/Reader。

  3. 另外,我们使用有向图(Directed Graph)进行拓扑中Node相关角色的存储。图的边(Edge)为Channel名称,图的顶点(Vertice)为Node


两个Node间主要有以下三种关系:


  1. UPSTREAM:如果Node A中有Channel C的Writer,而Node B中有Channel C的Reader,那么Node A被叫做Node B的上游。

  2. DOWNSTREAM:如果Node A中有Channel C的Reader,而Node B中有Channel C的Writer,那么Node A被叫做Node B的下游,两个Node可以互为上下游。

  3. UNREACHABLE:Node A和Node B没有Channel相关联。


你可以通过TopologyManager的AddChangeListener来监听整个系统中拓扑的变化。

 



拓扑发现主要处理两个动作:


  1. Join。一个角色加入拓扑。

  2. Leave。一个角色离开拓扑。


这两个动作都需要被组播给相同Domain中的其它角色,并且,其它角色的历史动作也需要被新加入角色所熟知。为此建立如下的拓扑发现流程:

 

  1. 初始化TopologyManager,创建RTPS的Participant,这类似于Cyber RT的Node,可以用来创建拓扑消息的Publisher和Subscriber。同时注册一个对端Participant变动的回调——OnParticipantChange。

  2. 每个进程创建上述三种Manager,该Manager会创建对应的Publisher和Subscriber(使用的Channel名称为*_change_broadcast)。设置Publisher的QOS策略为HISTORY_KEEP_ALL,这样,当有其它进程创建拓扑的Subscriber时,本进程发送过的拓扑Join或者Leave消息将会发送给新加 入的节点,保证整个拓扑的连续性和完整性。

  3. 当创建Node、Writer/Reader、Server/Client时,调用对应Manager的Join函数,请求加入拓扑。同时,由于上述QOS的设置,我们会收到其它进程的历史拓扑消息。

  4. 当收到其它角色的拓扑加入请求时,更新本地拓扑结构。Cyber RT要求每个Node拥有唯一的命名,如果在拓扑里发现同名Node,则比较两者的时间戳,时间戳小的Node保留。

  5. 当一个Participant退出时(OnParticipantChange被调用),将该Participant相关的拓扑从本地移除。





根据拓扑中的主机IP和进程名称,我们可以对一个Channel的Writer和Reader进行关系划分,以采用恰当的通信方式,提高通信效率。


  1. NO_RELATION:这两个Writer和Reader之间没有直接关系,也就是它们不是共用的一个Channel。

  2. DIFF_HOST:不同主机,不同主机间的Writer和Reader只能使用RTPS进行通信。

  3. DIFF_PROC:同一主机,不同进程。同一主机不同进程既可以使用RTPS进行通信,也可以使用共享内存的方式。默认为共享内存通信方式,可以通过配置进行更改。

  4. SAME_PROC:同一进程的Writer和Reader直接使用指针传参的方式进行通信。


同时,我们可以通过拓扑查询某些节点的存活状态、验证整个DAG是否完整。

另外,拓扑消息中还会夹带Channel的proto_type,proto_desc等用于消息序列化/反序列化。


本文从对“拓扑”概念开始,对“和谁进行通信”问题进行了解答。阿波君向大家介绍了三种通信角色,同时扩展了拓扑管理者的作用。最重要的是详细地解释了拓扑发现方式、发现流程及拓扑发现的应用。


阅读完今天的文章,热爱学习的你是否对Cyber RT拓扑发现有了进一步的了解呢?关于“如何进行通信”你又有怎样的疑惑和认识呢?


可以添加『Apollo小哥哥』为好友

进开发者交流群进行交流互动






您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存