(四)ODL Openflowplugin Master选举及Context服务实例化源码分析

作者简介:陈卓文,国内某游戏公司私有云团队开发者,主要从事SDN/NFV开发。

由于篇幅问题,我们将“Openflowplugin中Switch生命周期”这个大问题拆分为几个篇章:Switch生命周期对象ContextChain创建;控制节点的Master选举及ContextChain/Context服务实例化;MastershipChangeService以ReconciliationFramework;控制节点成为Slave;Switch下线过程。
本文为Openflowplugin(0.6.2)源码分析第四篇,控制节点的Master选举及ContextChain/Context服务实例化,个人认为是Openflowplugin中最核心一篇!

附:
第一篇:(一)ODL OpenflowPlugin启动流程源码分析
第二篇:(二)ODL Openflowplugin Switch连上控制器Handshake过程源码分析
第三篇:(三)ODL Openflowplugin Switch生命周期对象ContextChain创建源码分析

读者约定:基本掌握Opendaylight的思想/有一定实践经验,想要深入理解openflowplugin源码/想对openflowplugin源码修改。

回顾上一篇核心观点:“在Switch完成Handshake后,Openflowplugin会为Switch创建各个Context对象(Device/Rpc/Statistics/Role),以及ContextChain对象。”引出本文核心问题:在多个控制器情况下,当Switch设置多个控制器(比如ovs:set-controller),那么每个控制器,Openflowplugin都会为switch创建ContextChain对象,那么哪个控制器节点会向上层提供Switch的服务?比如下发流表。

结论:Openflow协议支持多个控制器,控制器有角色有三类master、slave、equal。本文仅讨论Master/Slave,当控制器节点为Switch的Master,该控制器的Openflowplugin为上层应用提供该Switch的服务。

一般来说,为了控制层高可用使用master/slave模式;为了控制器负载均衡使用equal模式;

1.Master选举(Cluster Singleton Service)

在上一篇《ODL Openflowplugin Switch生命周期对象ContextChain创建源码分析》笔记最后留下了悬念,在ContextChainHolderImpl.createContextChain方法的最后代码是Master选举的关键:

接下来我们详细剖析此行代码!

ContextChainImpl.registerServices方法如下:

方法是将当前ContextChainImpl对象注册为ClusterSingletonService。这是opendaylight/mdsal的接口,它作用是在控制器集群节点中为这一个service进行选举,最终只会在选举出来的leader节点中运行此serivce,所以称为Singleton service。注意:可以看到ContextChain实现了ClusterSingletonService接口。

如果是集群情况,那么各个控制节点会选举,如果不是集群,那么当前节点就会成为master。

注:Opendaylight为集群环境提供了Singleton Service以及EntityOwnershipService,具体可以参考ODL官网,后续我会为此两服务展开深入剖析笔记!

根据Cluster Singleton Service的实现,当某个节点成为此service的leader,首先会在此节点中调用此service自身的instantiateServiceInstance方法。所以,可以思考到Openflowplugin运行集群情况下,底层Switch必须设置所有集群节点为其控制器,这样在每个控制器都创建ContextChain对象都会注册Singleton Service,最终由底层决定某一个节点成某个switch的ContextChain服务的Leader并运行其instantiateServiceInstance方法进行实例化服务!

总结:Openflowplugin为每个Switch创建ContextChain,ContextChain作为一个Cluster Singleton service。本质上的Switch的控制器的Master选举,就是ContextChain的Cluster Singleton Service选举。

2.实例化ContextChain服务实例

如上面所述,当ContextChain作为一个Singleton service选举,成为Leader的节点就会运行其ContextChainImpl.instantiateServiceInstance方法:

可以看到方法逻辑是调用上一步传入的各个Context的instantiateServiceInstance方法。如果有任何异常都调用ContextChainHolderImpl.onNotAbleToStartMastership方法(会销毁ContextChain及各个Context)。

而调用Context的instantiateServiceInstance方法,即GuardedContextImpl.instantiateServiceInstance:

实际上是调用:DeviceContext/RpcContext/StatisticsContext/RoleContext的instantiateServiceInstance方法。

先给出结论:当四个Context的instantiateServiceInstance方法都成功执行完成,当前控制器正式成为Switch的Master,并可通过“钩子”触发上层北向应用。

2.1 DeviceContext实例化服务

下面展开DeviceContextImpl.instantiateServiceInstance具体过程。实例化DeviceContextImpl,需要执行很多逻辑。包括:
(1)lazyTransactionManagerInitialization(),会创建TransactionChainManager对象;创建DeviceFlowRegistryImpl对象;创建DeviceGroupRegistryImpl对象;创建DeviceMeterRegistryImpl对象。

(2)解析portStatusMessages,将switch上的nodeConnector(port)写入operational YANG。注意:此时刚刚Handshake完成后,应该是没有port的,后面步骤会请求底层port信息。

(3)根据Device openflow版本号,选择不同的initializer(OF10DeviceInitializer或OF13DeviceInitializer)进行处似乎还,初始化会进行。

  • 1.将switch node写入Operational YANG: inventory node;
  • 2.解析capabilities, 写入deviceContext.deviceState;
  • 3.发消息请求switch获取switch各个特性。包括:table/group/meter/port description等信息,并写到operational yang中

(4)调用DeviceFlowRegistryImpl.fill(), 读取ovs node的FlowCapableNode的节点的流(从YANG),注意DeviceFlowRegistryImpl对象是ofp中缓存了一份完整流表。

(5)读取FlowCapableNode完成后, 回调DeviceFlowRegistryCallback对象; 最终会调用ContextChainHolderImpl.onMasterRoleAcquired方法, 传入参数状态是INITIAL_FLOW_REGISTRY_FILL。

关注一下,所以当DeviceContext对象初始化完成后,最终调用ContextChainHolderImpl.onMasterRoleAcquired方法。给出结论,当各个Context实例化服务实例最后都会调用此方法。当所有Context都完成调用后,说明Switch对应的ContextChain及Context完成实例化,并能提供服务。

2.2 RpcContext实例化服务

RpcContext的instantiateServiceInstance方法主要完成:
(1)主要是给rpcContext注册各种rpc实现,用于上层调用(比如下发流表SalFlowService)。在RpcContext实例化过程中,会实例化并注册所有Rpc服务,提供给上层调用。具体RPC服务注册及使用,在下一篇笔记展开。
(2)在注册各种rpc实现后,调用ContextChainHolderImpl.onMasterRoleAcquired方法,传入参数状态是RPC_REGISTRATION

其中调用MdSalRegistrationUtils.registerServices方法中可以看到实例化各种RPC Service并注册。

2.3 StatisticsContext实例化服务

实例化StatisticsContext,会提供Statistics数据收集服务。当然这需要额外的性能消耗,我们可以关闭数据收集以提高性能,会在后续笔记具体展开。

在其instantiateServiceInstance方法中,会根据配置和Switch的特性,确定需要收集的数据类型,并最后调用gatherDynamicData方法收集动态数据,当收集成功后回调InitialSubmitCallback

instantiateServiceInstance方法如下:

gatherDynamicData方法收集动态数据:会判断switch是否在线(没有断连),然后根据刚刚在instantiateServiceInstance方法中设置的收集数据列表进行数据收集,会发请求到switch。在gatherDynamicData方法中,实现的是一次根据需要收集数据的类型,向Switch发送请求收集数据,并且在YANG中更新数据收集时间戳。(具体收集数据过程在另一篇笔记展开)

而回调对象InitialSubmitCallback中,当gatherDynamicData方法执行成功后会首先调用ContextChainHolderImpl.onMasterRoleAcquired方法,且传入参数状态为INITIAL_GATHERING,表示完成初始化的收集数据(第一次收集)。

并且在这里会判断是否使用ReconciliationFramework。如果使用了,会调用continueInitializationAfterReconciliation方法开启持续收集数据的服务。如果不使用,会持续收集信息。在调用方法中,会再次调用ContextChainHolderImpl.onMasterRoleAcquired方法,传入参数状态为INITIAL_SUBMIT

需要注意,ReconciliationFramework是Openflowplugin额外扩展的实现用于Switch协商的应用,主要是提供有优先级的上层服务启动,是一个钩子感知底层ofp成为Switch的Master的一个实现,后面笔记会深入剖析。

在此InitialSubmitCallback回调中如果使用ReconciliationFramework就不会立即开启持续收集数据,而是在ReconciliationFramework处理完后,才再调用continueInitializationAfterReconciliation方法开启持续收集数据的服务。此处具体逻辑,可以在后面看到。

2.4 RoleContext实例化服务

初始化RoleContext服务,是向底层Switch发送消息,通知其当前控制节点成为其Master。具体实现中,当Openflow版本大于等于1.3,在这里会直接调用set-role rpc,通知Switch当前控制器节点是master(BECOMEMASTER)。

完成set-role rpc调用成功后(BECOMEMASTER),会回调MasterRoleCallback,最终会调用ContextChainHolderImpl.onMasterRoleAcquired方法,且传入状态为MASTER_ON_DEVICE

3.控制器成为Switch的Master

实例化各个服务完成后,控制器正式成为Switch的Master。可以看到在各个context(device/rpc/statistics/role)初始化完成后,都会调用ContextChainHolderImpl.onMasterRoleAcquired方法,且传入不同的状态。现在让我们来展开在onMasterRoleAcquired方法。onMasterRoleAcquired方法是判断Switch在控制节点完成各个服务实例化的核心。是Openflowplugin对上层应用提供触发钩子的核心方法。

会根据是否使用了ReconciliationFramework,有两个判断方式ContextChain是否已经成为master。在这里我们可以回顾一下在StatisticsContext中实例化服务时,当使用ReconciliationFramework不会立即开启数据收集,即不会再次调用onMasterRoleAcquired方法并传入状态INITIAL_SUBMIT。

所以在onMasterRoleAcquired方法中有体现,在调用contextChain.isMastered方法判断是否已经成为Master(各个服务实例化完成),在调用isMastered方法除了传入当前状态,还会传入第二个参数意味着是否在ReconciliationFramework的步骤中。

当使用了ReconciliationFramework且传入状态不是INITIAL_SUBMIT,证明是还在ReconciliationFramework的步骤中。当传入状态是INITIAL_SUBMIT,只会出现在调用StatisticsContextImpl.continueInitializationAfterReconciliation方法,即不开启ReconciliationFramework(StatisticsContext中)情况,或者ReconciliationFramework处理完成后才会调用。

当在ReconciliationFramework的步骤中,会传入第二个参数为true,否则传入参数为false

3.1 判断控制器节点为Master

contextChain.isMastered方法中,会判断控制器节点是否成为Switch的Master。可以注意下面一个小细节,当在ReconciliationFramework步骤(传入参数true)时,如果已经是Master也不会马上改变ContextChain及Context状态为WORKING_MASTER,仅仅直接返回值为True表示isMaster,但是还没是WORKING_MASTER。原因在于ReconciliationFramework会有额外处理,最后再会回调此方法,再设置为WORKING_MASTER。需要结合后面笔记,这里算是埋下伏笔吧。

在isMastered方法中,会根据调用传入的状态,设置对应其类属性标识。且最都会一起判断各个标识位,当各个当各个context(device/rpc/statistics/role)都完成初始化,就会表示Openflowplugin中已经完成服务实例化,即已经成为Switch的Master,会返回true

关注一下判断Master逻辑:inReconciliationFrameworkStep和initialSubmitting是互斥关系(回顾上面的StatisticsContext流程)

最后如果不在ReconciliationFramework步骤中(第二个传入参数),会改变contextChain和各个context状态为WORKING_MASTER。

回到ContextChainHolderImpl.onMasterRoleAcquired方法中:
1)如果使用ReconciliationFramework,且isMastered(方法返回true)情况下,会调用ownershipChangeListener.becomeMasterBeforeSubmittedDS(deviceInfo)方法。
且有额外的回调reconciliationFrameworkCallback,其会调用statisticsContext.continueInitializationAfterReconciliation方法开启statisticsContext中的持续收集信息。注意在statisticsContext初始化时,会根据使用reconciliationFramework跳过开启持续收集信息,目的是在这里完成ReconciliationFramework调用后再开启。

2)不使用ReconciliationFramework时,且isMastered(方法返回true)情况下:会调用ownershipChangeListener.becomeMaster;再调用deviceManager向inventory通知device node节点添加;

先给出结论,当完成Switch的ContextChain在leader节点上实例化后,会调用MastershipChangeServiceManager方法,其为ofp底层对上层应用提供的钩子触发服务。当实例化完成(isMasterd)后,触发上层应用。如果使用ReconciliationFramework,则调用becomeMasterBeforeSubmittedDS方法,否则调用becomeMaster方法。

由于篇幅问题,我们在下一笔记才继续深入MastershipChangeServiceManager。留下疑问:MastershipChangeServiceManager是如何作为钩子,为上层提供感知节点成为Switch的Master呢?

4.总结

在本文中,我可以了解到控制器节点作为Switch的Master选举是直接通过ODL controller底层提供的Cluster Singleton Service实现。

且我们深入看到在控制器节点选举成为Master后,会进行各个Context服务的实例化,包括Device,Rpc,Statistics,Role。只有当完成所有Context的实例化,Openflowplugin才能对北向应用提供此Switch的服务。

最后,提出一个观点:MastershipChangeServiceManager,其为上层感知节点成为Switch的Master提供钩子。让我们下篇再见!


  • 本站原创文章仅代表作者观点,不代表SDNLAB立场。所有原创内容版权均属SDNLAB,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用,转载须注明来自 SDNLAB并附上本文链接。 本站中所有编译类文章仅用于学习和交流目的,编译工作遵照 CC 协议,如果有侵犯到您权益的地方,请及时联系我们。
  • 本文链接https://www.sdnlab.com/22309.html
分享到:
相关文章
条评论

登录后才可以评论

陈卓文 发表于18-09-10
1