前言:
为了方便灵活性,ONOS采取的是一种模块化结构,一方面能灵活地组织各种模块,容易让开发者扩展出新的模块,同时通过隔离令系统的模块各司其职而不会互相干扰。实际上ONOS是由多个子系统组成,本文将对ONOS中几个比较有代表性的子系统进行介绍。
基础——OSGi:
ONOS由多个模块组合而成,实际上ONOS是基于OSGi bundles实现的。OSGi是一个基于插件式的软件架构,包含OSGi框架和插件。这种插件被称之为Bundle,Bundle可以被动态地加载和卸载,动态升级也就可以被实现了(有点像Erlang的OTP提供的热代码替换,不过OTP和Erlang结合更紧密),通过使用OSGi,Java应用就可以实现良好的模块化。OSGi框架规范提供了一个通用的安全的Java框架,Bundle服务应用的部署、扩展全都依赖于该框架。
OSGi体系架构:
JVM运行在硬件上,JVM上包含Execution Environment、Modules、Life Cycle、Services、Security等内容。事实上,OSGi是一个非常强大,同样非常复杂的框架。ONOS使用了它,能大大提升灵活性。
ONOS设计目标:
ONOS的设计目标包含以下几点:
1.代码的模块化:扩展其他组件更容易。
2.可配置性:灵活的配置能实现灵活的架构,同时也能提高可定制性。
3.问题的分离:每个模块负责自身所属的工作内容。如果子系统间有明确的界限,就可以充分利用模块化的好处。
4.协议不可知:ONOS本身和它的应用都不应该被绑定到特定的协议库或实现。
在ONOS中,每个子系统都有自己的源码树,ONOS吸收了Maven的分层POM组织方式,因而每个子项目拥有自己的pom.xml文件。
至于配置方面,因为ONOS使用了Karaf作为其OSGi框架,这使得动态模块载入成为可能,同时Karaf提供了诸如允许使用标准JAX-RS API去开发REST API使其更安全、运行时方便日志级别的设置和容易扩展的CLI等特性。
在ONOS中,Protocol-aware network-facing模块被用于与网络的交互,Protocol-agnostic system core用于跟踪和服务与网络状态的信息等,应用程序与core通过北向API通讯,而network-facing模块使用南向API与core通讯,通过层层分离,实现模块化。
如果我们要使用一种新的协议,我们必须能够构建出一个相应的network-facing模块,作为一个插件在运行时加载至ONOS。
ONOS子系统结构:
ONOS中,一个子系统是一系列服务的集合。
ONOS定义了几个主要的subsystem,如:
Device Subsystem:管理基础设备的详细清单;
Link Subsystem:管理基础链接的详细清单;
Host Subsystem:管理终端主机和它们在网络中的位置;
还有一些诸如Topology Subsystem、FlowRule Subsystem等子系统。
在ONOS中,一个子系统的组件驻留在三个主要层,并且可以由一个或多个Java接口实现,如图所示:
Provider:
这是ONOS堆栈中最底层的部分。Provider接口通过特定协议的库通向网络,通过ProviderService接口调用core。protocol-aware provider负责使用多种控制和配置协议与网络互动,同时提供特定服务的感知(sensory)数据给core。有时Provider也会收集来自其他子系统的数据,转换为特定服务的数据。
在Provider中还包含Provider Id,一个Provider必须和一个Id关联标识。
一个子系统可能会包含多个Provider,可以指定Provider是主Provider还是从属的Provider。在ONOS的Device Subsystem中能支持多个Provider。
Manager:
Manager是一个驻留在core中的组件,Manager负责接受来自Provider的信息、为上层应用和服务提供服务等工作。
它提供了数个接口:
一个用于给其他组件读取网络状态的北向接口;
一个用于执行管理命令和应用网络状态的AdminService接口;
一个被Provider用于注册的ProviderRegistry南向接口;
一个提供给已经注册的Provider用来对manager收发信息的ProviderService南向接口;
在core中有一个Store的组件,与Manager紧密结合,它主要负责索引、持久化和同步来自Manager的消息。
Application:
应用程序通过AdminService和其他服务接口聚合消息,被Manager使用和操作。应用程序的功能多种多样,比如显示网络拓扑、节点等。
Application和Provider一样要和一个Id关联,这里称之为ApplicationId。被ONOS用来跟踪应用程序的上下文。一个应用程序若想得到一个合法ID,它必须提供它的名字,使用CoreService注册。
几个子系统的简单介绍:
1. Provider的职责例子——Device Subsystem
这个子系统负责发现和跟踪组成网络的设备,同时允许操作者和应用程序控制它们。大多数的ONOS核心子系统都依赖于这个子系统所创建和管理的Device和Port对象模型或其provider被用于与网络交互。
Device Subsystem包含以下几个部分:
一个DeviceManager,通过DeviceProviderService接口与多个Provider关联,通过DeviceService接口与多个监听者(listener)关联。
DeviceProviders,每一个都有自己的网络协议库的支持。
一个DeviceStore,跟踪Device模型对象和生成DeviceEvents。
下图是OpenFlow Subsystem的示意图,可以清楚地看到其南向接口和OF控制器的交互过程:
2.Store的职责例子——集群协调
如果我们部署一套多实例ONOS,实际上它是由多个拥有一个唯一的NodeId的实例或节点组成的集群。每一个节点都可以感知网络的一部分状态。本地的状态分段由节点管理,在集群中以事件传播。事件被Store生成,它们通过分布式储存与集群中的所有节点共享。
根据具体服务的需求,储存的内容可以有不同的特征,如强一致性或最终一致性,这使得每个服务的储存根据需求采用合适的分布机制。
目前ONOS主控部分采用Hazelcast以达到强一致性,而Device、Link等部分的管理使用乐观的复制技术辅以gossip协议以确保最终一致性。
如果两个不同节点上的子系统是相同的,子系统将会直接通过Store与另一个进行同步。但是同步的只是一部分的状态,如,对于DeviceStore,它只知道设备的状态而不了解其他的,如怎样跟踪链接状态的信息。
目前除了拓扑管理这部分,其他所有服务都要访问分布式储存。
两个子系统间的同步示意图如下:
结语:
本文介绍了ONOS的模块化架构及子系统的结构,并通过具体的两个例子介绍子系统中一些概念的运用情况。希望本文能对各位研究ONOS的研究者有所帮助。