深入OpenFlowPlugin源码集群模式的Master选举(三)


【编者的话】OpenFlow协议支持多个控制器,其工作模式是怎样的?在OFP中,控制器节点会选举Master,该Master节点为北向应用提供该交换机的服务。本文深入OpenFlowPlugin中的Master选举过程,以及北向应用怎么感知选举并处理。

OpenFlow协议支持多个控制器,在多个控制器情况下,哪个控制器节点会向北向应用提供Switch的服务?在OFP中,当控制器节点成为Master,该控制器为北向应用提供该Switch的服务。本文深入OpenFlowPlugin中的Master选举过程,以及北向的应用怎么感知选举并处理。


OpenFlow协议定义控制器有角色有三类Master、Slave、Equal,本文仅讨论Master/Slave。一般来说,为了控制层高可用使用Master/Slave模式;为了控制器负载均衡使用Equal模式。

Master选举(Cluster Singleton Service)

在上一篇《深入OpenFlowPlugin源码Switch生命周期对象》文章中,在最后留下了悬念,ContextChainHolderImpl.createContextChain方法的最后代码是Master选举的关键:
contextChain.registerServices(singletonServiceProvider);

ContextChainImpl.registerServices方法如下:
01.jpg

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

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


注:OpenDaylight为集群环境提供了Singleton Service以及EntityOwnershipService。
根据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选举。

实例化ContextChain服务实例

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

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

分别调用了四个核心的Context,完成Master节点的相关服务创建注册等。
  • DeviceContext:提供设备信息的,包括将设备写入YANG等等;
  • RpcContext:注册OFP封装的接口RPC,为上层应用提供接口。比如,下发流表在OFP是通过提供一个内部RPC服务,这些服务的注册都封装于RpcContext中;
  • StatisticsContext:静态信息采集,可根据配置最终确定是否采集数据;
  • RoleContext:封装状态选举,比如其会通知设备当前节点是Master。


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

控制器成为Switch的Master

实例化各个服务完成后,控制器正式成为Switch的Master。各个Context(Device/RPC/Statistics/Role)初始化完成后,都会调用ContextChainHolderImpl.onMasterRoleAcquired方法,且传入不同的状态。现在让我们来详细分析onMasterRoleAcquired方法。onMasterRoleAcquired方法是判断Switch在控制节点完成各个服务实例化的核心。是OpenFlowPlugin对上层应用提供触发钩子的核心方法。
03.jpg

判断控制器节点为Master

contextChain.isMastered方法中,会判断控制器节点是否成为Switch的Master。
04.jpg



可以注意一个小细节,当在ReconciliationFramework步骤(传入参数true)时,如果已经是Master也不会马上改变ContextChain及Context状态为WORKING_MASTER,仅仅直接返回值为True表示isMaster,但是还没是WORKING_MASTER。原因在于ReconciliationFramework会有额外处理,最后再会回调此方法,再设置为WORKING_MASTER
在isMastered方法中,会根据调用传入的状态,设置对应其类属性标识。且最都会一起判断各个标识位,当各个当各个Context(Device/RPC/Statistics/Role)都完成初始化,就会表示OpenFlowPlugin中已经完成服务实例化,即已经成为Switch的Master,会返回true

当完成Switch的ContextChain在leader节点上实例化后,会调用MastershipChangeServiceManager方法,其为ofp底层对上层应用提供的钩子触发服务。当实例化完成(isMasterd)后,触发上层应用。如果使用ReconciliationFramework,则调用becomeMasterBeforeSubmittedDS方法,否则调用becomeMaster方法。这两个也是OpenFlowPlugin留给我们的钩子,让上层应用可以感知device上线后写选举初始化完成,触发我们上层北向应用!

MastershipChangeServiceManager最初设计

先来看看不使用ReconciliationFramework是怎样的过程?

当Switch ContextChain选举成功且实例化完成后,当没有使用ReconciliationFramework时就会调用此方法becomeMaster我个人理解,这个OpenFlowPlugin最开始设计提供钩子,在最开始设计是没有ReconciliationFramework,我们的应用同样可以感知“Switch选举后且完整初始化完成(isMaster)”

MastershipChangeServiceManager.becomeMaster方法,核心逻辑是调用serviceGroup变量中所有的service的onBecomeOwner方法:
@Override
public void becomeMaster(@Nonnull final DeviceInfo deviceInfo) {
    serviceGroup.forEach(mastershipChangeService -> mastershipChangeService.onBecomeOwner(deviceInfo));


serviceGroup变量中的Service是通过调用MastershipChangeServiceManager.register方法注册:
@Nonnull
@Override
public MastershipChangeRegistration register(@Nonnull MastershipChangeService service) {
    final MastershipServiceDelegate registration =
            new MastershipServiceDelegate(service, () -> serviceGroup.remove(service));
    serviceGroup.add(service);
    if (masterChecker != null && masterChecker.isAnyDeviceMastered()) {
        masterChecker.listOfMasteredDevices().forEach(service::onBecomeOwner);
    }
    return registration;


所以在不使用ReconciliationFramework情况下,上层应用可以直接在OSGi引用MastershipChangeServiceManager,调用其Register方法注册服务,这样当ofp成为Switch的Master就会触发我们注册的服务(实现特定接口:实现方法onBecomeOwner等)。

可以看到becomeMaster最为直接粗暴,这样做有什么缺点?为什么后面会出现ReconciliationFramework,它是为了解决什么问题?


官方解读:When the switch is connected, all the applications including FRM(Forwarding Rules Manager) will receive the node added DTCN(Data Tree Change Listener) and starts pushing the flows for the openflow switch. FRM reconciliation will read the data from the config and starts pushing the flows one by one. In the meantime, applications can react to the node added DTCN change and will start pushing the flows through the config DS. With this, there is a high chance the application flow can be overwritten by the old flows by FRM via reconciliation.
个人理解,当上层有很多个应用时,那么当成为Master调用becomeMaster方法,各个方法都马上执行,可能会发生冲突,导致流表出错等。且只能靠应用注册先后顺序,来决定开始执行顺序。

ReconciliationFramework

个人理解ReconciliationFramework是用于协调各个应用与Switch上线的框架。可实现Switch上线,按优先级触发北向注册的应用。当Switch contextChain选举成功后,且各个Context均初始化完成后,当使用了ReconciliationFramework就会调用方法MastershipChangeServiceManager.becomeMasterBeforeSubmittedDS

其最终会轮询registeredServices变量中的Services并调用reconcileServices方法,即回调所有注册的服务
private ListenableFuture<ResultState> reconcileNode(DeviceInfo node) {
    ListenableFuture<ResultState> lastFuture = Futures.immediateFuture(null);
    for (List<ReconciliationNotificationListener> services : registeredServices.values()) {
        lastFuture = reconcileServices(lastFuture, services, node);
    }
    return lastFuture;


回调所有注册的服务是根据其注册的优先级来实现顺序的调用!所以,我们也可以通过注册服务到

ReconciliationFramework来实现感知底层节点上线并成为Master。

总结

  • 控制器节点作为Switch的Master选举是直接通过ODL controller底层提供的Cluster Singleton Service实现;
  • 控制器节点选举成为Master后,会进行各个Context服务的实例化,只有当完成所有Context的实例化,OpenFlowPlugin才能对北向应用提供此Switch的服务;
  • 北向应用可以通过MastershipChangeServiceManager和ReconciliationFramework感知节点上线并处理。

0 个评论

要回复文章请先登录注册