ODL技术内幕:架构设计与实现原理(txt+pdf+epub+mobi电子书下载)


发布时间:2021-04-25 00:25:03

点击下载

作者:耿兴元

出版社:机械工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

ODL技术内幕:架构设计与实现原理

ODL技术内幕:架构设计与实现原理试读:

前言

OpenDaylight(简称ODL)项目是Linux基金会旗下的一个开源合作项目,致力于推进软件定义网络(SDN)和网络功能虚拟化(NFV)的发展,目的是寻求以一种更透明的方式促进该领域的创新。该组织由行业领先者建立,旨在制定一个统一、开放的平台,驾驭合作开发的力量,以驱动产业和生态圈的创新。ODL是针对企业、服务提供商、数据中心、WAN的模块化的开放的SDN平台,其基于OSGi的微服务架构让用户能够按需部署网络服务、应用、协议和插件。ODL平台基本每半年发布一次大版本,从2013年开始,项目经历了多个版本的迭代已趋于成熟和稳定,几乎成为网络创新应用场景的默认选择。

ODL把被控制的网络看作是一个消息驱动的巨大状态机,因此该平台核心架构即其模型驱动的状态保存机制与消息转发机制,称为模型驱动的业务抽象层(MD-SAL)。该架构的魅力源于其架构的前瞻性、可塑性和长期演进能力。

ODL在架构设计上的先进性和灵活性,使其成为SDN领域最有影响力的开源平台。灵活的插件机制与在规模上的弹性可扩展,使ODL可应用于智慧城市和其他IoT应用等涉及多种设备类型以及多种网络技术的场景,包括光交换、IP/MPLS、LTE或5G无线网络。ODL对这些技术的可编程性可以做到设备无关。如今,ODL在各场景的网络创新中的应用越来越广泛,利用和贡献ODL项目的中国公司数量也在不断增长,包括华为、联想、瑞斯康达、腾讯、Zenlayer、中兴、阿里巴巴和百度等。2017年3月,中兴通讯成为国内首家ODL白金会员。为什么写这本书

ODL不仅仅是一个SDN控制器平台,它还是一个优秀的模型驱动架构实现,以及一个典型的分布式系统设计范例。通过ODL,我们能学习的不仅仅是SDN,也能学到其通用的编程技术及软件架构设计,其分布式系统设计实现也非常值得我们借鉴。

但是,ODL作为一个开源项目,也有令人诟病的地方,主要有两点:一是虽然ODL架构设计比较先进,代码实现也比较优秀,但ODL缺乏较为系统性的文档,而且仅有的一些文档更新也较为滞后,内容陈旧,容易误导新手;再加上语言和文化背景的差异,足以让大量国内ODL初级玩家望而却步。二是ODL的架构演进非常快,核心模块和接口变动频繁,再加上ODL子项目众多,导致ODL功能和接口碎片化严重,开发者一开始面对几百万行代码,确实有点“老虎吃天,无从下口”的感觉。

我作为一个一直从事软件研发工作的工程师,深知学习与应用ODL的不易,所以我想是不是可以把我之前学习ODL的笔记——对ODL源码的分析和对ODL架构设计的理解整理成书,进而帮助大家深入理解ODL设计原理和思想,把握其核心源码实现,以不变应万变。这对大家基于ODL平台进行业务研发及应用都能有所裨益。本书的读者对象

本书适合所有有志于解决现有网络问题并促进网络变革的通信、网络及计算机行业相关从业者,特别是希望掌握软件定义网络热门技术的开发人员,还适合具有一定工作经验、关注网络热门技术并希望查漏补缺继续成长的程序员,以及具备一定软件开发能力的网络技术领域从业者。

具备一定的Java语言开发基础,了解网络基础知识及分布式系统基础知识将有助于读者更好地理解本书中的内容。本书的主要内容

对于广大有志于投身网络变革大潮的从业者而言,ODL依然具有很高的门槛——100多个子项目,几百万行源代码,OSGi、Maven、Akka、YANG等背景知识,都成了相关从业者应用ODL平台的“拦路虎”。面对这些障碍,我们需要抓住ODL平台框架的本质与核心——MD-SAL,只有真正理解ODL的这个核心框架设计,理解MD-SAL的核心源码实现及其设计思想,才能基于ODL进行高效的SDN开发实战,就如同习武练功,招式是外壳,内功心法是核心,二者要相辅相成。本书结合作者15年的通信软件研发从业经验,从ODL核心框架MD-SAL的实现源码入手进行解构,剖析代码中的设计模式,总结ODL中的软件架构设计思想。本书可谓一本重在讲授内功心法,并指导内功和招式结合的“武功秘籍”。

本书能帮助入门级程序员深入、直观地理解ODL技术原理,构建精准的知识框架;帮助有一定工作经验的程序员填补知识漏洞,打通知识体系;帮助正在应用ODL构建商用产品和应用的同仁们客观认识并分析ODL中现存的问题。本书还分享了作者在基于ODL进行商用开发时总结的若干实战经验。勘误与支持

本书主要内容来源于本人研究学习ODL源码的笔记和在应用ODL开发项目过程中的实践经验。我们知道ODL社区非常活跃,版本发布频繁,架构调整及源码变动也比较大,这不可避免地会导致书中引用的源代码与ODL社区最新源代码有一定出入,请读者在阅读过程中务必注意。同时,由于作者写作和认知水平有限,问题在所难免,欢迎读者朋友们通过电子邮箱yfc@hzbook.com进行指正。致谢

ODL官方社区的源代码是创作本书的原始素材,因此我首先感谢ODL官方社区。

其次,我要感谢未来网络学院给予我与大家分享ODL技术的平台,以及在开源项目Jaguar的成立、运作管理和基础设施资源上的支持。

最后,感谢中兴通讯IT学院的闫林老师的鼓励和巨大帮助。耿兴元2019年第一部分 基础环境篇

·第1章 阅读源代码前的准备

·第2章 ODL项目管理设计详解第1章 阅读源代码前的准备

OpenDaylight(简称ODL)是在2013年由18家网络巨头发起成立的,旨在推动SDN发展及促进网络领域创新的开源控制器平台项目。ODL项目的目标是成为SDN领域的开发、运行、创新的框架和平台。开源项目自有其天生的优势和劣势,也必须遵循自身的发展演进的规律。开源项目优势可总结为具有兼容并包的框架性设计,聚集了众多贡献者大胆创新的思想,版本迭代快速等。开源项目的劣势也很明显,那就是开源项目一般缺乏系统性、完善的文档,部署、升级和运维监控等方面考虑的也都有所欠缺,所以自身很难提供针对具体场景的端到端的商用解决方案。另外,对于一个比较活跃的开源项目,需要5~7年才能做到框架的成熟和稳定。ODL项目成立至今已有6年多,我们可以说其核心框架已经稳定和成熟了。因此,理解并掌握ODL的最新核心框架的设计与实现原理,对于我们利用ODL这个框架和平台进行商用产品的研发是有很大帮助的。

本章主要为后续章节做准备,将指导大家搭建ODL的编译开发环境,也会向大家简单介绍ODL的诸多子项目以及这些项目的组织管理方式,并对ODL核心的MD-SAL框架的设计目标和设计原则做一个简单的介绍,让大家对ODL项目及其核心架构有一个整体的了解。1.1 ODL项目介绍

ODL项目成立之初,发起成立该项目的众多网络巨头都拿出了自己在SDN领域或网络虚拟化方面的一些项目代码贡献到ODL社区,包括Cisco的OnePk(ODL中的controller子项目)、Big Switch的控制器与网络虚拟化项目(ODL中的OSCP子项目)、IBM的DOVE(ODL中的OpenDove子项目)、Radware的安全防御系统(ODL中的Defence4All子项目)、NEC的Virtual Tenent Network(ODL中VTN子项目的)等。这些项目本身都是由各公司自己开发的,有些还是已经商用的项目。虽然这些项目本身质量还可以,但是因为缺乏统一的框架和设计思路,有些项目还具有竞争性质,导致这些项目没法组合成一个有机的整体,因此,我们看到的ODL的初始发布版本(氢版本),就是一个拼凑起来的大杂烩。随着近年来的不断完善,ODL逐渐形成了统一的架构和合理的项目层次。1.1.1 ODL框架之争

在最初的ODL众多子项目中,Cisco主导的controller子项目和Big Switch主导的OSCP项目代表了SDN控制器框架设计的两种思路,二者属于竞争关系。

controller项目中,基于平台化的设计思路,提出了业务抽象层(Service Abstraction Layer,SAL)的概念,把控制器分为南向(SB)协议插件、北向(NB)业务/应用插件和SAL三层。通过SAL层,实现了多种南向协议插件与多样化的业务应用的解耦,这种设计借鉴了早期的SDN开源控制器Beacon的基于OSGi的模块化框架设计,符合ONF提出的典型的SDN三层架构,每一层都暴露大量的API供不同层次的业务应用进行调用,使系统具有很强的扩展性和灵活性。

OSCP项目中,主要采用了产品化的设计思路,南向协议绑定在OpenFlow上,提供集成度高的、功能比较完善的网络基础功能管理,但这将导致整个系统围绕着OpenFlow协议紧紧地耦合在一起,限制了控制器自身的扩展性与适用性。

当然,我们知道,Cisco的思路在ODL社区最终胜出,成为ODL的核心框架。而Big Switch与Cisco在ODL社区角力失败也导致了其在ODL社区运作了还不到3个月的时间就退出了。1.1.2 SAL的演进

最初的SAL是以AD-SAL(API-Driven SAL)为主的,也就是需要分别定义南向插件的Java编程接口(API)和业务应用的Java编程接口(API),并需要为两种接口做大量的适配编码。另外,北向的REST接口也要手工定义。显而易见的,作为一个开放的开发平台来说,增加一个新的插件功能,就需要通过手工编码来定义SAL API和适配代码,使其具有很大局限性。一方面API的定义非常困难,因为这需要非常专业的网络领域的知识,还要考虑规范性、通用性和扩展性;另一方面,大量的手工编码对于开发者来说非常不友好。因此,从ODL的氦(Hellium)版本和锂(Lithium)版本开始,一直到氟(Fluorine)版本,MD-SAL(Model-Driven SAL)架构逐步发展并成熟,而AD-SAL从铍(Berryllium)版本即被完全废弃。截至现在,ODL社区加入了越来越多的基于MD-SAL框架设计的南向协议类的项目和应用类项目(几十个),而ODL成立时建立的一些不太符合该设计思路的项目,比如OSCP、Defence4All、OpenDove等现在已经被社区归档,不再继续维护。1.1.3 ODL的子项目及分类

MD-SAL架构采用YANG语言作为数据及接口的建模语言,通过YangTools工具提供了编译期数据模型与接口的解析和代码的自动生成,采用Binding Broker、Binding-Inde-pendent Broker两套接口实现了运行期的数据模型与接口的适配转换,简化并规范了南向插件与业务应用间调用接口的定义,为南向插件和业务应用的开发者提供了统一的开发模式。MD-SAL框架的主体代码原本在controller和yangtools两个项目中,特别的是,controller项目最初不仅包含SAL框架,还包括配置子系统、netconf/restconf、版本公共配置及版本打包、项目模板等功能。随着ODL项目的发展演进,这些功能有的单独成立子项目(mdsal、odlparent、netconf/restconf、archetypes),有的被废弃(配置子系统、AD-SAL),当前仍保留在controller项目中的功能代码主要是ODL的分布式集群功能(分布式datastore和remoterpc)和blueprint扩展。以上controller、mdsal、odlparent、netconf/restconf等子项目加上yangtools项目基本上就构成了ODL的核心框架,再加上ODL的鉴权框架AAA项目,这些子项目就是ODL的核心项目。除了决定ODL基础架构的这些核心项目,ODL的项目中还包括协议类项目、业务应用类项目及支持类项目。协议类项目包括多种南向协议插件项目如OpenFlow、OVSDB、NETCONF、BGP、BMP、PCEP、LISP、SNMP、P4、SXP、OCP、P4、Telemetry等,还包括北向的RESTCONF、NEMO Intent等。业务应用类项目包括NetVirt、COE、FaaS、BIER APP、DetNet、SFC、Transport PCE、IOT等,支持类项目包括Documentation、Inte-gration、RelEng等。图1-1显示了ODL社区现在的活跃的项目及项目间的依赖关系。注意 因为ODL社区中不断接受申请成立新的子项目,原来的子项目也会根据情况进行调整,甚至被废弃而归档,因此图1-1中的项目不一定与最新的ODL子项目一一对应,但从几个核心项目来说,图1-1还算准确。图1-1 ODL子项目及其依赖关系图1.1.4 ODL项目的管理

ODL的项目除了支撑类项目使用的Python、Shell脚本语言,其他大部分项目都是使用Java语言。采用Java语言作为开发语言的项目,大量的开源第三方组件及项目间的依赖管理是一件令人头疼的事情,而ODL社区借助Maven这款优秀的项目管理工具,实现了ODL项目的依赖下载、编译、构建、测试、打包、部署等一系列功能。

Maven工具通过pom配置文件来声明项目的依赖和编译构建选项。对于一个ODL的项目,只要其根目录下有pom文件,执行如下命令,即可实现项目的第三方组件的依赖下载、编译、测试、打包和安装到本地仓库的功能。mvn clean install

当然,要想执行上述命令,必须先安装JDK和Maven,并正确配置环境变量。1.2节会简单讲解安装ODL编译构建环境的过程。1.2 搭建ODL编译构建环境

操作系统推荐使用Linux的发行版本Ubuntu或者Mac OS X,如果选择Windows的话,需要注意有些ODL项目是编译不过的。1.2.1 安装JDK

JDK(Java Development Kit)是Java语言的软件开发工具,JDK是整个Java语言开发的核心,它包含了Java的运行环境、Java工具和Java基础的类库。ODL的大部分项目是采用Java语言编写的,因此要编译构建ODL项目,首先要安装对应的JDK版本。截至目前,ODL已经发布了9个大的版本,编译前3个发布版本(氢、氦、锂)的代码需要安装JDK 7版本,编译后6个版本(铍、硼、碳、氮、氧、氟)的代码需要安装JDK 8版本。ODL社区最新计划从第10个版本(也就是钠版本)开始,采用JDK 11版本(兼容JDK 8)。下面以JDK 8版本为例介绍其安装和配置过程,其他版本的JDK安装参考Oracle官方文档即可。1.JDK下载安装

JDK 8下载地址:

https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

Mac OS X或者Windows操作系统,请下载对应操作系统类型的安装包,下载后安装即可。

Linux操作系统可以下载JDK 8压缩包解压到某个目录下,也可以采用下面的命令直接安装。Fedora:sudo dnf install java-1.8.0-openjdk java-1.8.0-openjdk-develUbuntu:sudo apt-get install openjdk-8-jdk

安装后,在控制台终端执行命令java–version验证JDK是否安装成功。安装成功会打印如下信息:java version "1.8.0_201"Java(TM) SE Runtime Environment (build 1.8.0_201-b09)Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)2.设置环境变量

对于Windows操作系统,按“我的电脑→属性→高级→环境变量→用户变量→新建(N)”路径添加环境变量JAVA_HOME和JAVA_TOOL_OPTIONS,如图1-2、图1-3所示。图1-2 JAVA_HOME环境变量设置图1-3 JAVA_TOOL_OPTIONS环境变量设置

在Path环境变量中加入%JAVA_HOME%\bin

对于Linux或Mac OS X操作系统,通过配置文件~/.bash_profile或/etc/profile配置环境变量。export JAVA_HOME={YOUR_JDK_INSTALLED_DIR}export PATH=$JAVA_HOME/bin:$PATH1.2.2 安装及配置Maven1.Maven安装

Maven下载地址(推荐安装最新的Maven 3.6.0,编译ODL最新版本代码不得低于3.5.2):http://maven.apache.org/download.cgi,下载后解压到某个目录即可。

解压Maven后,在/etc/profile中配置环境变量MAVEN_HOME,在PATH下增加$MAVEN_HOME/bin路径。export MAVEN_HOME={WHERE_YOU_UNZIPPED_MAVEN}/apache-maven-{MVN_VERSION}export PATH=$MAVEN_HOME/bin:$PATHexport MAVEN_OPTS="-Xmx1024m"

Windows操作系统请按照1.2.1的方式增加这3个环境变量。注意 使用参数MAVEN_OPTS设置Maven工具构建项目时,设置Java虚拟机最大可用内存。构建ODL的项目时,Java默认的最大可用内存是不够的,需要把这个值设置得大一些,至少1024M。如果开发机器允许,这个参数还可以设置得更大一些。

执行命令mvn–v验证Maven是否成功。成功会显示如下内容:Apache Maven 3.5.3 (3383c37e1f9e9b3bc3df5050c29c8aff9f295297; 2018-02-25T03: 49:05+08:00)Maven home: /usr/share/mavenJava version: 1.8.0_161, vendor: Oracle CorporationJava home: /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.161-0.b14.el7_4.x86_64/jreDefault locale: en_US, platform encoding: UTF-8OS name: "linux", version: "3.10.0-693.2.2.el7.x86_64", arch: "amd64", family: "unix"2.Maven配置

ODL维护了独立于Maven中央仓库的一个Maven仓库,如果不修改Maven默认的settings.xml,是无法访问ODL发布的组件的。要编译构建ODL的项目或者基于ODL开发自己的应用,必须要依赖ODL发布的组件,因此必须把https://github.com/opendaylight/odlparent/blob/master/settings.xml复制到~/.m2/settings.xml或者覆盖$MAVEN_HOME/conf目录中的settings.xml。

如果你是通过代理上网的,那还要在settings.xml里设置上网代理,如代码清单1-1所示。

代码清单1-1 Maven上网代理配置 http-proxynj true http yourproxy.abc.com 80 10.*|*.abc.com https-proxynj true https yourproxy.abc.com 80 10.*|*.abc.com

详细说明可参考http://maven.apache.org/guides/mini/guide-proxies.html。1.3 阅读和调试ODL源代码

安装好JDK与Maven后,就可以对ODL项目进行编译构建了。如果想方便地阅读和调试ODL项目源码,安装一个好用的集成开发(IDE)工具是十分必要的。推荐安装IntelliJ IDEA这款IDE工具,使用其阅读和调试代码非常方便。1.3.1 ODL项目源码下载

ODL是通过Git仓库管理所有项目的源码,ODL官方仓库地址https://git.opendaylight.org。

Linux操作系统建议先安装git工具。Fedora:sudo dnf install gitUbuntu:sudo apt-get install git-core

安装好git工具后,通过浏览器打开https://git.opendaylight.org,点击Projects→List可以看到ODL所有的子项目,选择你感兴趣的项目,比如AAA。在General标签下,可以找到通过git工具克隆AAA项目源码库的命令,如图1-4所示。图1-4 AAA项目

然后复制命令git clone https://git.opendaylight.org/gerrit/aaa执行,这样就可以把AAA项目的源码克隆到本地。

进入AAA目录,执行命令git branch–a查看该项目所有的分支,执行命令git tag–list查看该项目所有的tag。

如果想查看某一分支或者tag的源码,执行git checkout[branch or tag]:git checkout release/fluorine-sr2

即把本地代码切换成最新发布的Fluorine-SR2版本。

你也可以直接通过ODL在GitHub上的镜像库(https://www.github.com/opendaylight)下载各项目的源码。打开链接后,选择感兴趣的项目,在branch下拉菜单里选择分支或者tag,然后点击Clone or download→Download ZIP,下载源码包后解压即可。

进入到AAA目录下执行命令mvn clean install即可构建该项目。1.3.2 IntelliJ IDEA安装

进入官网https://www.jetbrains.com/idea/download,选择适合版本下载IntelliJ IDEA。注意 IntelliJ IDEA分为社区免费版和商业版,如果财力允许,可以选择安装商业版。一般来说,社区免费版也够用了。

读者可以按照提示或者参考网上的安装指导完成IntelliJ IDEA的安装。1.3.3 IntelliJ IDEA调试ODL的项目源码

要通过IntelliJ IDEA调试跟踪ODL子项目的源码,首先要下载ODL的某个发行版本并带debug参数启动该版本。ODL版本下载地址https://docs.opendaylight.org/en/latest/downloads.html,请选择合适的ODL发布版本下载。下载后解压到某个目录,进入解压目录,通过命令./bin/karaf debug启动ODL,在karaf控制台通过feature install命令安装该子项目相关的feature,这样才能通过IntelliJ IDEA调试该版本源代码。

确保该子项目源码启动的是上述ODL版本tag的源码,然后在IDEA里直接导入该子项目,也可以在该子项目的根目录执行mvn idea:idea生成IDEA工程。用IDEA打开后缀为.ipr的工程文件,推荐用mvn idea:idea的方式,因为其可以提前下载依赖并发现构建的问题。在IDEA里打开该子项目工程后,依次选择Run→Debug→Edit Configurations,然后选择列表中的Remote方式,在Host处填写ODL运行的服务器的IP,Port为5005,如图1-5所示。最后点击图1-5中的Debug按钮即可对ODL的源码进行调试跟踪。图1-5 调试ODL项目源码的配置

当然,阅读调试ODL源码的目的不仅仅是为了查找Bug、定位问题。分析源代码的实现流程和设计思路也有助于我们更好地理解ODL架构设计和实现原理,这也是本书的主旨所在。1.4 ODL设计目标

SDN(Software Defined Network,软件定义网络)的运动来自一个简单的问题:为什么网络设备不应像其他计算平台一样可编程?SDN的设计理念通过分解传统的垂直集成的网络设备堆栈,并将控制平面重构为独立于网络设备的操作系统,可以实现如下几个长远目标:

·来自不同供应商的不同物理和虚拟设备类型的互操作性。

·提供网络流量从源到目的的可视性。

·面向所有设备的通用的管理框架。

·可根据用户需求塑造网络行为的可编程性。

·基于策略的自动化。

ODL作为SDN设计理念中控制与管理面的开发及运行平台(网络操作系统),是迄今为止这个新堆栈中最大和最成熟的项目,逐渐成为新开放网络生态系统的核心组件。

ODL作为一个SDN控制器运行与开发平台,在架构设计上考虑了如下关键需求。

·灵活性:SDN控制器必须能容纳大量的各类型应用。同时,控制器应用应该是使用通用的框架和编程模型,提供一致的API给客户端。这对于发现并解决故障、系统集成、组合多种应用为更高级的编排流都是十分重要的。

·开发过程规模化:控制器架构必须允许插件、业务组件、应用能相互独立进行开发,能够灵活地选择功能特性进行集成。

·组件的运行时安装与卸载:控制器必须能够在运行时安装新的协议、业务及应用插件。控制器的基础架构需要适应动态安装的插件或从设备动态中发现的数据模型,运行时的扩展性允许控制器适应网络的变化(新设备或新网络特性),避免传统EMS、NMS冗长的发布周期。

·性能与规模:控制器应该能够在多样化的环境中,使得承担不同的负载/应用都运行良好。当然,性能不应该通过在模块化上花费大量代价来获得。控制器架构应该被允许在集群、云环境中进行水平扩展,平台需要能为其提供一致性的集群支持。

为了支持SDN应用的开发,控制器也应该提供满足如下需求的应用开发环境。

·使用领域模型语言描述内部和外部的系统行为,会促进开发人员和网络专家的协作,方便系统集成。领域模型语言和代码生成工具应该提供API和协议的快速进化(敏捷)。控制器使用的领域语言、技术、工具对于一些通用的网络概念,比如业务、服务链、用户管理和策略等都要是可用的。

·控制器使用的模型工具应该与设备的模型工具一致,这样控制器和设备就可以使用通用的工具链,设备模型在控制器中也可以被重用,使用这些模型的控制器应用/插件与设备之间即可实现无缝对接。工具链也应该支持业务和设备的模型间的适配代码的生成。1.5 ODL总体架构

了解了ODL平台的设计背景和设计目标,会帮助我们理解ODL的整体架构。考虑到平台必须灵活地支持多种南向协议插件,支持多样化的业务及应用,支持运行时的组件安装与卸载,那么,整个平台就必须是模块化的架构设计,模块间要尽量松耦合,模块间交互要有统一的方式和标准。基于此,ODL所有组件都需要遵循Java平台事实上的动态模块化规范OSGi进行设计,直接基于Karaf这个强大的OSGi容器来提供组件的部署和运行环境。当然,OSGi规范的实现框架在Karaf的配置文件中可以配置为felix或者equinox。我们可以在解压的ODL发布版本的配置文件/etc/config.properties和/etc/custom.properties中看到如下相关配置:karaf.framework.equinox=mvn\:org.eclipse.platform/org.eclipse.osgi/3.12.100karaf.framework.felix=mvn\:org.apache.felix/org.apache.felix.framework/5.6.10# Use Equinox as default OSGi Framework Implementationkaraf.framework=equinox注意 从JDK 9开始,模块化已是Java提供的一个原生特性。截至ODL第9个发布版本,ODL还没有基于JDK 9及JDK 9以后的版本进行构建,因此其模块化仍然是遵循OSGi规范设计的。但ODL社区计划在第10个发布版本中基于JDK 11进行构建。

ODL把被控制和管理的网络抽象为一个以消息驱动的巨大的状态机,因此ODL架构中的消息机制与状态保存机制就成了整体架构中最基础的服务设施。为了简化并规范化消息与状态数据的定义,ODL社区引入YANG语言作为消息与状态数据的模型语言。在ODL中,通过YANG语言驱动设计的这些基础服务设施被称为模型驱动的服务抽象层(MD-SAL,Model-Driven Service Abstraction Layer),MD-SAL是ODL平台整体架构的核心,为南向协议插件和业务应用提供统一的服务调用接口。具体来说,ODL的MD-SAL提供了RPC、Notification、数据变更通知这3种消息机制,同时提供了DataStore来保存设备与业务的配置和状态(Config&Operational两种类的库)。如图1-6Platform部分所示。图1-6 ODL总体架构

由图1-6可见,MD-SAL是ODL整体架构的平台部分,提供了多种模块间的调用与交互机制。比较典型的包括:1)RPC提供了消费者与提供者之间一对一的调用路由机制;2)Notification提供了消息的订阅发布机制;3)DataStore提供了配置与状态数据的保存和查找机制,并提供了在集群环境中的数据细粒度分片与一致性保证。从MD-SAL架构来说,南向协议插件和业务/北向应用的生命周期都是一样的,每个南向协议插件和业务/应用都是一个OSGi的Bundle,遵循同样的设计思路,围绕MD-SAL架构提供的基础服务,通过YANG模型来定义其交互的接口标准。这样,无论是南向协议还是业务应用,都可以被看作基于MD-SAL架构的一个扩展插件,如图1-7所示。图1-7 基于MD-SAL的南向协议与业务应用插件

ODL通过YangTools实现了YANG模型的解析和自动生成接口代码,南向协议/业务应用插件只需要定义出YANG模型,MD-SAL不需要包含任何插件特定的代码和API,对所有加载到控制器的南向协议/业务应用插件都提供了通用的处理机制。通过YangTools工具,使得插件间的调用接口、RESTCONF接口都由YANG模型统一定义并自动生成。通过MD-SAL,实现了南向协议/业务应用插件间接口调用的运行时适配。1.6 本章小结

本章主要是为了下面更深入地理解ODL架构的设计原理做准备。通过本章的介绍我们应该学会搭建ODL的编译调试环境,理解MD-SAL是ODL架构的核心。当然,本章也提到ODL的众多子项目都是通过Maven工具进行管理的,第2章将介绍ODL社区在项目管理上碰到的若干问题以及相应的解决方案。第2章 ODL项目管理设计详解“罗马不是一天建成的”。同样,ODL也是历经多年才不断发展壮大。作为一个开源项目,在参与ODL的志愿者们的共同努力下,ODL在架构与项目管理方面持续得到演进,功能变得越来越多,架构日趋合理,项目管理的层次越来越清晰,社区及项目中的各种问题也逐步被解决。

在第1章我们了解到ODL采用了模块化的架构设计,现在ODL的子项目多达上百个,每个子项目又分为若干模块,可以说有数百个模块。这数百个模块从OSGi的视角来看就是几百个Bundle;从Maven的视角来看,就是几百个pom。对这种规模的项目进行管理不是一件容易的事情。因此,本章首先描述ODL社区在管理众多子项目过程中会遇到的若干问题,并将和读者一起回顾社区通过Maven工具解决这些问题的思路和设计原则,以及如何一步步优化并完善解决方案,最后给出社区总结的对于项目管理的最佳实践。2.1 问题的提出

最初接触ODL项目时,笔者曾被它的庞大和繁杂吓到了。有个比喻说,“ODL是一只会跳舞的大象”。一方面是因为ODL包含了大量的功能特性;另一方面是因为最初的ODL版本中的各子项目是由参与创立ODL的各公司独立开发贡献到社区的,根本没有统一的架构设计,也很难做到统一的项目管理,而且一些子项目本身也没有进行很好的设计。比如,ODL最初的版本中,Cisco主导贡献的ODL最核心的框架部分:controller项目里,就有如下典型问题:

·该项目没有统一规划parent,比如mdsal就定义了两个parent:sal-parent和comp-atibility parent,版本号都是1.1-SNAPSHOT,但这两个parent都继承自另一个版本号为1.4.2-SNAPSHOT的parent pom。

·很多模块的版本号缺乏规划,没有从其直接的parent继承,使其定义混乱。比如UserManager的pom中,其parent的版本定义为1.4.2-SNAPSHOT,该模块的版本号却被定义成0.4.2-SNAPSHOT。

·依赖不是从parent pom继承,而是直接罗列在当前的pom中。

其他子项目也有类似的问题主要包括以下几个方面,1)整个ODL项目缺乏统一规划的parent pom,各模块继承层次不清晰,构建依赖混乱,版本编译构建和集成的工作经常出现各种问题,无法稳定;2)各项目和模块的版本号缺乏统一规划,导致ODL的子项目的几百个模块都有不同的版本号,维护与演进非常麻烦和困难;3)发布版本过程中,需要花费大量的人力修复出错的pom文件。

这些问题不仅给项目自身的维护和开发带来了困难,同时给学习和使用ODL的用户也带来了困扰。用户很难梳理清楚各项目和模块的不同版本,特别是ODL最初的几个发布版本。因此,用户在加载和运行初始发布的ODL版本的过程中,要面对非常多的干扰。2.2 解决思路

所有用Maven管理的项目都应该是分模块的,每个模块都对应着一个pom.xml,pom.xml文件是Maven进行工作的主要配置文件。在这个文件中我们可以配置groupId、artifactId和version等Maven项目必需的元素,可以配置Maven项目需要使用的远程仓库,可以定义Maven项目打包的形式,也可以定义Maven项目的资源依赖关系等。对于一个最简单的pom.xml来说,必须包含modelVersion、groupId、artifactId和version这4个元素,当然其中的元素可以是从它的父项目中继承的。在Maven中,通过使用groupId、artifactId和version组成groupdId:artifactId:version的形式来确定唯一的一个项目(模块)。

对于如何处理所构建的多个模块间的关系,Maven给我们提供了一个pom的继承和聚合的功能。所谓聚合是可以通过一个pom将所有的要构建模块整合起来;所谓继承是在构建多个模块的时候,往往有多个模块会有相同的groupId、version或依赖,为了减少pom文件的配置,同面向对象的设计中类的继承一样,在父工程中配置了pom,子项目中的pom就可以继承。总之,聚合是为了方便高速构建项目,继承是为了消除重复配置,在简化pom的时候还能促进各个模块配置的一致性。两者的共同点是其packaging都是pom,聚合模块与继承关系中的父模块除了pom之外都没有实际内容。

ODL项目是通过Maven工具进行管理的,因此,对于上文ODL项目管理中碰到的问题,如何优化pom.xml的设计就是一个解决思路。对于公共编译配置和依赖管理的问题,ODL社区从第二个版本发布开始,成立了odlparent项目。该项目最初只有一个pom文件,这个pom文件里包含所有配置和依赖管理。顾名思义,这个项目的pom就是ODL所有其他项目的parent。从第1章我们了解到,ODL的模块是遵循OSGi规范而设计的,所有模块都要编译为bundle部署到OSGi容器里才能加载运行。因此,从第三个版本发布开始,bundle构建的公共配置也被放在odlparent中,也即bundle-parent。同时,编译构建bundle时的checkstyle配置文件也统一放在了odlparent项目中。第1章在搭建编译环境时,需要下载的Maven的settings.xml文件,也放到了odlparent中进行维护。在后续发布的版本中,odlparent项目中陆续加入了feature管理的parent,以及karaf打包的parent。这样,在ODL的子项目中,只需继承odlparent中相应的parent pom,就可继承这些公共配置,极大地简化了ODL子项目中pom的配置。

当然,我们不要忘了ODL的核心框架MD-SAL。在mdsal子项目中,有一个binding-parent的pom,这个pom包含了通过yangtools解析YANG模型所生成的binding代码的默认构建配置。对于所有遵循MD-SAL开发的模块(bundle)的构建,只需要继承这个pom,然后在你的pom中添加模块的自身依赖即可。

不仅是对parent pom的设计,包括各子项目中版本号规划,社区都给出了指导性建议,列在下面供读者参考:

·统一定义全局的parent pom,对所有子项目提供公共配置。

·除非必要,否则每个子项目只能有一个parent。

·所有子项目的parent都继承自全局parent pom。

·每个子项目中的模块的版本号要统一,版本号要按照..格式进行定义。

·项目依赖的版本号在parent pom里统一进行管理,在子项目的模块pom里不能对版本号硬编码。

·要对所有子项目使用一致的命名规范。注意 ODL的命名规范包括代码目录命名、模块坐标的命名规范、feature的命名规范。这里就不再详细说明了,如果想进一步详细了解的可以参考:https://wiki.opendaylight.org/view/CrossProject:HouseKeeping_Best_Practices_Group:Project_layout及https://wiki.opendaylight.org/view/CrossProject:Integration_Group:About_User_Facing_Features。

图2-1是按照odlparent项目发布的最新版本设计的parent pom继承关系示意图。图2-1 odlparent中父pom设计

在图2-1中,各pom的说明简单如下:

·odlparent-lite——最基础的父pom,被所有的ODL项目的Maven模块直接或者间接继承。可以供不生成发布坐标(artifacts)的Maven模块直接继承(比如聚合的POM)。

·odlparent——公共的父pom,供包含Java代码的Maven模块继承。

·bundle-parent——供生成OSGi Bundle的Maven模块继承的父pom。

·binding-parent——遵循MD-SAL架构设计的Maven模块继承的父pom。

·single-feature-parent——供生成单个Karaf 4feature的Maven模块继承的父pom。

·feature-repo-parent——供生成Karaf 4feature库的Maven模块继承的父pom。

·features-odlparent——ODL依赖的公共库的feature集合的库。

·karaf4-parent——供生成Karaf 4发布包的Maven模块所继承的父pom。注意 图2-1中虚框内的两个pom(dom-parent和binding-parent)不是在odlparent项目里定义的,而是在mdsal项目里定义的。

以上parent pom的详细说明以及在子项目中的继承应用参见2.3节和2.4节。2.3 实现详解

本节我们将对图2-1中pom文件的设计,主要是对pom包含的配置以及主要用途进行详细说明。2.3.1 基础parent设计

最基础的parent pom包括两个——odlparent-lite和odlparent,前者包括一些公共配置信息,后者则在前者的基础上增加了通用的第三方库的依赖。1.odlparent-lite

odlparent-lite是ODL所有的Maven项目和模块最基础的父pom,主要提供了以下公共配置信息。

·license information(许可证信息)。

·organization information(组织信息)。

·issue management information(a link to our Bugzilla)(问题管理)。

·continuous integration information(a link to our Jenkins setup)(持续集成信息,Jenkins的链接)。

·default Maven plugins(maven-clean-plugin,maven-deploy-plugin,maven-install-plugin,maven-javadoc-plugin with HelpMojo support,maven-project-info-reports-plugin,maven-site-plugin with Asciidoc support,jdepend-maven-plugin)(默认的Maven插件)。

·distribution management information(发布管理信息)。

·source code management(源码管理)。

pom中的具体配置如代码清单2-1所示。

代码清单2-1 odlparent-lite中的公共配置信息 Eclipse Public License v1.0 https://www.eclipse.org/legal/epl-v10.html OpenDaylight https://www.opendaylight.org Bugzilla https://bugs.opendaylight.org/ Jenkins https://jenkins.opendaylight.org/releng/ https://git.opendaylight.org/gerrit/注意 ODL的问题跟踪现已改为JIRA(https://jira.opendaylight.org/),原来的Bugzilla虽然还可以访问,但已不能在Bugzilla上提交Bug。

另外,在这个pom中还定义了几个有用的profile,以满足不同的环境或不同的构建要求。举一个例子,如代码清单2-2所示的这个profile。

代码清单2-2 odlparent-lite中的快速构建的profile q true true true true true true true true true true true true true true

使用该profile,只需要在执行构建命令时,加上参数-Pq(即mvn clean install-Pq),即可跳过测试、忽略代码检查、不生成site和文档等,加速构建的过程。

这个pom可直接被ODL子项目中聚合的pom所继承。2.odlparent

该pom继承自odlparent-lite,主要提供ODL项目的依赖和插件管理。

如果ODL的项目或你自己写的模块依赖到如下第三方库,就需要继承odlparent这个pom。

·Akka(and Scala)

·Apache Commons:

·commons-codec

·commons-fileupload

·commons-io

·commons-lang

·commons-lang3

·commons-net

·Apache Shiro

·Guava

·JAX-RS with Jersey

·JSON processing:

·GSON

·Jackson

·Logging:

·Logback

·SLF4J

·Netty

·OSGi:

·Apache Felix

·core OSGi dependencies(core,compendium…)

·Testing:

·Hamcrest

·JSON assert

·JUnit

·Mockito

·Pax Exam

·PowerMock

·XML/XSL:

·Xerces

·XML APIs注意 因为ODL所依赖的第三方库是动态的,可能会增加或删去某个第三方库依赖,所以这个列表不一定是完整准确的。

这个pom还配置了对Java源码的Checkstyle规则设置,特别的是对于所有Java代码,其强制必须附带EPL License的声明头。声明头格式要求如代码清单2-3所示。

代码清单2-3 EPL license header/* * Copyright ? ${year} ${holder} and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */

其中,${year}是代码发布年份,${holder}是发布该代码的版权所有者。2.3.2 模块构建

ODL的模块遵循OSGi规范,在OSGi中,模块即bundle。因此,构建ODL项目中的某个模块,即编译构建OSGi的bundle。另外,ODL的核心框架是MD-SAL,由于YANG模型是贯穿模块设计的,且其是模块交互的基础,因此,以YANG模型驱动的模块设计是ODL中普适的设计模式,所以构建包含YANG模型的模块就成了ODL各子项目的公共需求。1.bundle-parent

该pom继承自odlparent,这个pom主要用来配置OSGi bundle的构建。在该pom中:

·maven-javadoc-plugin被激活,用以构建Javadoc的JAR包。

·maven-source-plugin被激活,用以构建源码的JAR包。

·maven-bundle-plugin被激活(包括扩展),用以构建OSGi bundles(使用“bundle”类型打包)。

另外,在该pom中也增加了JUnit作为test范围的默认依赖,因此在bundle的编译构建过程中,默认是会执行单元测试的。2.dom-parent

这个pom不是在odlparent中定义的模块,而是在mdsal项目中。

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载