27

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

 5 years ago
source link: https://www.tuicool.com/articles/Vb2eIn7
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

【编者的话】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 方法如下:

IR7vYzR.jpg!web

方法是将当前 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 方法:

JvIrArj.jpg!web

可以看到方法逻辑是调用上一步传入的各个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对上层应用提供触发钩子的核心方法。

bMnQriy.jpg!web

判断控制器节点为Master

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

YfIFjuI.jpg!web

可以注意一个小细节,当在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感知节点上线并处理。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK