百度Apollo系统学习-Cyber RT 通信-服务发现

百度Apollo系统学习-Cyber RT 通信-服务发现

  • 前言
  • 基本概念
  • TopologyManager
  • 三张拓扑网
    • Manager
    • Node网
      • Node
      • NodeXxxImpl
      • NodeManager
    • Channel网
      • ChannelManager
    • Service网
      • Service & Client
      • ServiceManager
  • 最后仍旧盗一张总的结构图
  • 参考链接

前言

在这一章开始前,默认读者已经读完了专栏中有关cyberRT的注册启动以及通信部分的内容,在通信部分的最后我们遗留了一个问题,那就是在ReaderWriter初始化的时候会调用到一个JoinTheTopology函数,这个函数具体在做什么事情,也是我们这一章主要回答的问题。

基本概念

服务发现模块不负责具体消息的传递,而主要负责监测cyber中通信节点的存活情况,并且提醒已有节点有新节点加入并作出相应动作(比如某个channel多了一个读者,那么对应的写者就需要激活合适的Transmitter)。
NodeServer/Client/Writer/Reader的容器,Server/Client/Writer/Reader(注意Server在代码里其实是Service类,下面提到的Service是概念Service而不是代码里的Service)是有向图的顶点,ChannelWriterReader的边缘,ServiceServerClient的边缘。cyber中把WriterServer称作Upstream,另外两个是Downstream

TopologyManager

整个服务发现系统是一个全局的管理体系,每个process都有一个单例TopologyManagercyber/service_discovery/topology_manager.h),提供三个拓扑网的管理器NodeManagerChannelManagerServiceManager。所有的NodeNodeManager中被管理;所有的Channel以及ReaderWriter都在ChannelManager里;所有的Services以及ServerClient都在ServiceManager。目前从代码上看,其实TopologyManager的作用是监视网络中是否有参与者Participant退出或意外退出,而新参与者的加入是下属的三个管理器负责通知的。

  • TopologyManager里的消息是通过通信模式中的RTPS模式来进行通信的,也就是说通信系统实际上不依赖于服务发现系统,服务发现系统实际上是一个更高层面的管理。
  • 成员有一个RTPS中的参与者,在TopologyManager::Init()时会被创建,参与者的名字(不光是TopologyManager,整个服务发现网络的所有参与者名字都是这样组成的)由全局变量中的HostName()ProcessId()组成,监听的端口是11511(组件通过RTPS模式通信时的名字组成和这个一样,但端口是11512,具体见专栏里通信底层介绍的博客)。随之创建的还有该参与者的监听器(ParticipantListener,底层由fast-rtps实现)在该参与者发生变化的时候会调用,这是什么意思呢,其实就是TopologyManager本身也是这个网络中的一个一个参与者,只不过它负责监视并管理整个网络中的变化。
  • 另一个关键成员是participant_names_map记录了该拓扑中的其他参与者,在网络中有新的参与者加入或者有参与者退出时就会更新这个map。
  • TopologyManager::Convert函数主要是一个功能型的函数,它将fastrtps实现中的ParticipantDiscoveryInfo也就是参与者的变动信息重新包装成cyber中所需要的信息ChangeMsg,然后调用自己的信号成员回调之前注册的槽函数(请注意,目前在官方的代码中并没有发现TopologyManager有注册什么自己的回调函数,也就是说它的成员信号实际上是没用的,但用户可以根据需求注册槽,然后对服务发现网络的变动做出反应)。
  • TopologyManager的成员参与者participant_的监听器participant_listener_绑定了TopologyManager::OnParticipantChange函数,这个函数在有参与者离开时会通知三个拓扑网管理器这个消息(通过调用XxxManager::OnTopoModuleLeave()),然后发送信号调用注册的槽函数。这个监听器是在初始化时创建参与者TopologyManager::CreateParticipant()的时候绑定的,也就是说参与者成员每收到一条从底层的rtps发来的消息就会调用它。

三张拓扑网

Manager

Manager(在cyber/service_discovery/specific_manager/manager.h)是三张拓扑网的基类(非TopologyManager的基类),每个具体的Manager都是在TopologyManager创建的时候在TopologyManager::Init()中被创建并初始化的。Manager的成员主要就是一个fastrtps的publisher_和一个subscriber_以及订阅者对应的回调函数listener_。这个listener_是在Manager::CreateSubscriber()时绑定了Manager::OnRemoteChange()(回调函数会调用XxxManager::Dispose()来对这些消息进行处理),而每当有新的可供发现的东西加入或离开拓扑时(比如NodeReader等等)会调用Manager::Join()Manager::Leave(),这两个函数会通过RTPS底层库publish相应的消息,然后订阅者的回调函数listener_就会调用了。
当然它也和TopologyManager一样有一个信号。这个信号就是用来在Manager::Notify()时发送的,而注册槽的函数是Manager::AddChangeListener(),在Channel网络加入ReaderWriter会调用到这个注册函数,具体见Channel网解析。

Node网

管理node拓扑,在cyber/node/node_channel_impl.h中(Node被创建或销毁的时候)进行Join & Leave操作。这个网络主要是监察所有节点的存活,并提供查询接口。

Node

Node是通信网络中的基本单元,一个组件ComponentBase都会在初始化XxxComponent::Initialize()的时候创建一个只属于自己的Node(也可以通过cyber::CreateNode()创建),也就是说Node网中的每一个单元都是一个组件。
Node有自己的node_namename_spacenode_name来自于不同模块的配置文件.dag中的不同组件的config.namename_space好像还没见哪里用到过TODO

NodeXxxImpl

作为Node中两个成员,它们会在Node被创建的时候一并创建,也就是说,每个Node负责channel类型的通信节点(ReaderWriter),也负责service类型的通信节点(serviceclient)。而在这两个成员被创建时,如果当前是现实环境(is_reality_mode_),那么NodeChannelImpl就会调用service_discovery::NodeManager::Join()将当前节点加入拓扑,NodeServiceImpl则不会调用而是在创建Client&Service时才会调用ServiceManager::Join(非Node网络)。

NodeManager

多了一个NodeWarehouse nodes_的成员(NodeWarehouse那一套东西其实就是个线程安全的更高级的map),加入和离开拓扑即往nodes_AddRemove节点。NodeManager::Dispose()函数会根据消息种类来向nodes_中加入或删除节点,然后调用Notify()调用等待该信号的槽回调函数。

Channel网

管理ReaderWriter的channel拓扑。在ReaderWriter初始化时会加入拓扑(调用JoinTheTopology()),在它们被关掉的时候(Reader,Writer::Shutdown()调用的LeaveTheTopology())则离开拓扑。
JoinTheTopology()函数会先把Reader & Writer::OnChannelChange()注册到ChannelManager的槽中,这样当Channel网拓扑发生变化时就能调用回调函数OnChannelChange()了。然后对于写者,会去查找该Channel已有的所有读者并为它们Enable写者自己的的transmitter_;对于读者则会去查看该Channel已有的写者并为它们Enable读者自己的receiver_。最后把自己加入Channel网络拓扑中,加入引起拓扑变化后,该拓扑中对应channel的节点的回调函数都会被调用,写者加入对应读者的receiver被Enable,读者加入对应写者的transmitter被Enable。所以每次有读者或写者加入,所有涉及到的transmitterreceiver都会主动或被动地被Enable。
Reader::OnChannelChange()当发现有新的对应channel的读者加入时会调用自己receiver_::Enable(writer_attr)来注册一些回调函数,这样后面收到消息就能做出反应,具体见通信模块底层介绍的博客;Writer::OnChannelChange()当发现有新的Reader订阅自己这个channel时,会调用自己的transmitter_->Enable(reader_attr)(这里的reader_attr只有在HybridTransmitter才会用到,但因为默认就是Hybrid模式所以都会用到)来启用数据写入,如果已经启动过了那就略过。这里需要注意一点,那就是默认的传输方式是Hybrid,所以HybridTransmitter::Enable(opposite_attr)会根据参数来Enable最合适的Transmitter,也就是说当有新的读者加入拓扑网络时,相应channel的写者会去根据两者的关系启用最合适的Transmitter来发送消息。

ChannelManager

提供了新的成员来记录节点间的关系及节点网络的图结构,并分别以node_idchannel_id为key来保存读写者。和NodeManager的其他过程类似,只不过保存的信息和索引方式不同。

Service网

主要是监测service节点的存活并提供查询接口。

Service & Client

在通信模块上层结构中,Node存在有4种不同的基本单元:Writer, Reader, Service(即Server), ClientWriter拥有底层的TransmitterReader拥有底层的Receiver,它们的通信方法有三种,网络结构由Channel网管理,分别负责写和读。而对于Service & Client,它们都拥有Transmitter & ReceiverService接收request发送response,Client接收response发送request,通信方式为RTPS,网络结构由Service网管理。
所以Service & Client模式底层的通信还是借助于Transport,只不过是做成了service-client方式,上层也不像Writer, Reader那样借助DataVisitor等结构来通知,而是直接调用回调函数即可。它们也是依附于Node存在的,由Node的成员NodeServiceImpl提供创建方法。

ServiceManager

和其他Manager类似,也是保存了servers_, clients_两个列表,当有新的加入时,更新两张表,同时提供查询功能。它最主要的一个应用在cyber/service/client_base.hWaitForServiceNanoseconds()函数中调用了ServiceManager::HasService()函数来确定某个service是否存在。

最后仍旧盗一张总的结构图

百度Apollo系统学习-Cyber RT 通信-服务发现_第1张图片

参考链接

百度Apollo系统学习-Cyber RT 通信-上层
百度Apollo系统学习-Cyber RT 通信-底层
Apollo 3.5 Cyber - Service Discovery 模塊

你可能感兴趣的:(百度Apollo学习,自动驾驶,c++,服务器)