单雅辉 刘青凯 杨章 田鸿运 邹勇刚
摘要: 随着软件复杂度的增加和交付需求的变化,快速集成和自动部署成为高性能数值模拟软件推广应用的瓶颈。为满足软件构建和发布的差异化需求,简化从用户需求到软件发布的工作流程,基于Jenkins设计持续集成平台,实现软件静态审查、编译、测试和发布流程的自动化,全面记录软件构建日志和测试结果。利用Docker技术将构建环境容器化,实现环境的快速搭建和配置管理,满足多样化目标环境需求。该平台的实际应用效果显示,基于该平台的产品发布周期相比之前缩短约75%,可极大简化软件安装和部署难度。
关键词: 持续集成; 软件测试; 软件发布; 自动部署
中图分类号: TP311.56 文献标志码: B
Abstract: With the software complexity increasing and the delivery requirements changing, rapid integration and automatic deployment become the bottleneck in the application of high-performance numerical simulation software. In order to meet the differentiated requirements of software construction and release, the workflow from user requirements to software distribution is simplified, and then the continuous integration platform based on Jenkins is designed to realize the automation of software static review, compilation, testing and release process, in which the software build logs and test results can be recorded comprehensively. The Docker technology is used to containerize the environment, and then the rapid construction and configuration management of the environment can be realized to meet the needs of diversified target environment. The application effect of the platform shows that the product distribution cycle based on this platform is about 75% shorter than before, which can greatly simplify the difficulty of software installation and deployment.
Key words: continuous integration; software testing; software release; automatic deployment
0 引 言
数值模拟软件是一类特殊的计算机应用软件,其服务于科学计算,以再現、发现和预测真实客观系统运行规律和演化特征的数值模拟为主要目标。[1]目前,数值模拟软件已广泛应用于国家重大领域,包括全球气候预测、地球资源环境检测、核能开发利用、电磁环境和信息安全等。
随着数值模拟软件应用范围不断扩大,数值模拟软件的研发呈现以下3个方面特征[2]:(1)应用需求日趋复杂,软件规模不断增加,代码行数由过去的几千行发展到数万行甚至数十万行;(2)高效能计算共性技术不断发展,基于编程框架与离散中台的研发模式日益普及,使得软件架构趋于层次化和模块化,软件集成复杂度随之增加;(3)软件运行环境多样、交付部署频繁,为保证求解问题的规模,数值模拟软件在计算实际应用问题时需要高性能计算机支撑,但是不同高性能计算机在硬件架构、编译器、MPI、作业调度等方面存在较大差别,这种运行环境差异会对数值模拟软件的计算结果精度、性能表现等产生干扰,严重情况下甚至导致程序无法正常运行,这对软件的可移植性、部署灵活性提出更高的要求。
因此,在数值模拟软件研发过程中,如何降低集成和部署难度、满足产品化和应用推广需求,成为急需解决的问题。
本文结合高性能数值模拟软件研发过程中的实际需求,设计并实现一种适用于高性能数值模拟软件研发的持续集成平台;介绍数值模拟软件交付过程中面临的实际问题,对比分析几款典型的软件构建工具;介绍持续集成平台的操作流程和设计方案,阐述实施过程中的关键技术点和具体实施过程。
1 数值模拟软件交付过程面临的问题和挑战 数值模拟软件的交付过程涉及环境构建、依赖管理解析、软件编译、测试和部署等内容,如果仅涉及依赖关系处理和编译,业内一些构建工具(如CMake)可以有效支撑,但对于整个交付过程来说,业内流行的构建工具暂时不能满足需求。数值模拟软件交付过程具有以下几个方面的需求特征。
(1)生产环境的有效配置管理。数值模拟软件的研发和使用大多在Linux系统环境下进行。为保证软件安装包的可用性,生产环境需要与用户环境保持一致,通常采用搭建虚拟机的方式模拟用户环境。生产环境搭建过程中需完成操作系统安装、网络配置、软件驱动、编译器安装和环境配置等工作。该过程往往无法被记录,配置人员的某个错误操作极可能造成软件编译部署失败,并且难以定位错误的位置。因此,生产环境最好能够自动创建,并且每次环境配置的变更都能够被记录下来。
(2)编译语言与目标存在差异。在层次化研发模式中,按照软件的不同功能定位,数值模拟软件分为编程框架、离散中台和应用软件3类。数值模拟软件趋于模块化,各模块研发相对独立,模块或软件之间依赖关系复杂。不同类型的软件依赖关系不同,编译目标也会不同。此外,数值模拟软件大多基于C、C+ +、Fortran等编程语言混合编写,程序的编译方式也会存在一定的差异。因此,需要构建一套不仅能够支持不同程序语言、编译方式,而且能够自动解析、有效处理依赖关系的工具。
(3)跨平台兼容性测试。在通常情况下,软件集成、开发和测试等过程是在开发环境下完成的,之后才会向生产环境部署。对于数值模拟软件来说,程序对编译和运行时的环境依赖较为敏感。当生产环境与开发环境不一致时,经常引起依赖库版本不匹配、接口不兼容等问题,导致程序出现编译或运行错误。解决这类问题一般需要对程序进行适配性修改,然后重新提请测试和部署,但是这种方式没有在目标环境中进行充分测试,无法保证程序的正确性。解决方案是将生产环境下的测试、部署和发布活动纳入到数值模拟软件研发过程中,在开发的同时完成生产环境的测试,及时发现软件在生产环境中遇到的问题或存在的缺陷。
(4)一键式软件安装部署。完成软件构建后,将编译生成的二进制可执行程序、用户文档及其依赖的第三方库打包后供用户使用。由于用户环境配置不同,需要手工修改配置文件中的目录结构和环境配置信息,解析依赖关系与可执行程序链接库,并通过执行程序检查可用性。软件越复杂,依赖关系越复杂,安装部署所需时间越长,而且越容易出现错误。这对用户来说并不友好,影响程序的推广应用。因此,构建工具应该可以支持用户环境下依赖关系、安装与配置环境变量的自动处理,简化用户部署难度。
(5)全面记录构建日志和测试结果。数值模拟软件开发涉及数学、物理、计算机等多学科领域,开发人员之间的知识背景不同,对软件的理解差别很大。在软件构建和测试过程中发生错误时,无法快速定位错误是由环境配置、程序自身还是第三方依赖关系所引入,联合调试难度大。因此,持续集成平台需要将环境配置信息、编译日志和测试结果全面记录下来,并保存错误现场,便于开发人员分析和定位错误。
为解决以上问题,调研几款业内知名的软件构建和部署工具,其功能对比见表1。
Make是经典的构建工具之一,目前仍然活跃在软件开发领域,但是当应用程序复杂程度和软件依赖关系增加时,Makefile维护成本提升,导致Make更加难以调试。CMake是开源跨平台构建工具,能够处理混合语言编译,但暂不支持構建环境和自动解析依赖等功能。MSBuild、Ant、Maven和Gradle的应用领域主要针对Java或.NET语言,其中Gradle功能最为完善,可支持依赖解析、生命周期管理和构建环境管理等功能[3-8],但其支持语言受限,无法满足数值模拟领域多种编程语言混合编译的需求。
目前,尚未发现单一的工具软件可以完全符合上述高性能数值模拟软件构建和部署的需求,因此,针对数值模拟软件交付过程中存在的问题,借鉴DevOps思路[9],设计并实现一套面向数值模拟软件的持续集成平台。
2 持续集成与测试平台
为解决前文提出的数值模拟软件构建和部署过程中存在的问题,设计实现一种面向高性能数值模拟软件的持续集成平台。持续集成是一种软件开发 实践活动,通过单元测试和集成测试,将本地开发创建的代码更改提交到代码仓库中,触发自动化的软件构建操作,包括代码编译、静态代码审查、测试覆盖率检查、自动化验收测试和软件安装包发布等,验证更改是否满足质量和正确性的要求,从而尽早地发现集成错误。[10]该平台主要解决以下关键问题:(1)简化从用户需求到软件产品发布的工作流程,尽早发现程序缺陷;(2)满足多样化目标环境需求,实现环境的快速搭建与配置管理;(3)有效管理软件依赖关系,增强软件构建部署能力。
2.1 关键技术点和系统特色
2.1.1 自动化通用流程设计
针对传统工具系统构建流程繁琐、用户需求响应不及时的问题,设计一套自动化软件持续集成流程,尽量减少人工干预。该流程涉及产品发布的整个工作流,支持代码静态分析、编译部署、验收测试、测试覆盖率检测和产品发布等过程的自动化,其工作流程见图1。
该流程的输入是软件源代码,输出是二进制安装包。该流程的基础是通过版本控制工具统一管理源代码,制定规范进行分支、目录和权限管理。当研发人员收到用户的需求或缺陷反馈后,对本地代码进行修改,并完成本地单元级、模块级测试验证后,将源代码提交到版本管理系统。当版本管理系统检查到源代码仓库的状态发生变化后,自动或定时触发集成服务器进入构建过程。持续集成系统通过任务形式将源代码分发到指定从节点(按环境需求)进行系统构建和测试,具体包括代码静态审查、自动化测试、覆盖率测试等。测试通过后将软件编译成二进制安装包,并将安装包通过文件传输工具上传至产品发布平台或部署到目标机,通知用户下载、安装软件产品。如果系统构建失败,则通过网页的形式将报错日志反馈到控制台输出界面,供研发人员快速跟踪定位错误。
2.1.2 基于模板快速配置构建环境
满足多样化目标环境需求的关键是实现构建环境的自动化搭建,并对环境进行有效的版本控制。对虚拟化技术的前期调研发现,应用容器引擎技术能够将构建环境搭建的工作量最小化。
应用容器引擎将所需软件及其依赖关系包进一个可移植的容器中,支持向任何现有的Linux机器部署和迁移。容器是一组能够随处运行的单元,对应用程序及其关联性进行隔离,运行时相互之间不影响。根据特定的用户环境需求,容器引擎可通过环境构建脚本快速创建容器环境。构建脚本将全部环境配置命令组合形成文件模板,通过一条简单的环境构建命令即可实现容器化构建环境的快速生成和批量创建。
与虚拟机相比,容器化环境更加轻量化。当出现新的构建环境需求时,只需要简单修改模板文件,即可实现快速定制,环境搭建时间由原来的几小时缩短为几分钟。此外,这种方式便于开发人员与测试人员之间沟通迭代,通过交换环境构建脚本可保证软件执行环境的一致性。
2.1.3 联动构建机制管理依赖关系
在数值模拟软件研制过程中,存在2种较为常见的依赖关系,即库依赖和组件依赖。库依赖是指程序开发过程中所依赖的第三方软件包,例如编译器、MPI和数学库等,这些软件一般很少更新。组件依赖应用程序所依赖的部分程序块通常是自主研发的,需要频繁更新。[10]
对于库依赖来说,由于不同软件所用的第三方软件包有所差异,在集成或部署时经常遇到版本冲突、接口不兼容等问题。通过对所有产品库依赖关系进行梳理,基于软件包管理工具建立统一的库管理模式,可形成一套根据构建环境分类的内部发布平台(软件源)。开发人员只需要在原有构建工具的基础上进行封装,简单编写配置文件,明确构建步骤和依赖关系,即可从内部发布平台(软件源)自动解析获取依赖,完成编译和软件打包等操作,具体产品构建工作流程见图2。
对于组件依赖来说,当某个组件被修改时,仅独立编译该组件,在集成时会影响相关组件的使用。针对这一问题,基于持续集成系统配置联动构建机制,即建立任务之间的前后顺序管理,当前一组件构建成功即可自动触发下一组件构建,通过集成测试后,再将该应用程序依赖的框架或库整理打包并发布。
统一的依赖库管理模式与联动构建机制相结合,一方面可提供统一的第三方库管理机制,有效管理库版本,实现第三方库依赖关系的自动解析;另一方面可有效管理组件之间的依赖关系和持续集成与测试组件之间的接口,避免组件版本不兼容引入的问题。
2.2 持续集成方案设计
按照第2.1节中的流程设计思路,基于持续集成服务器与版本控制系统之间的触发机制,当系统检测到代码更新时,持续集成服务器选择指定的从节点作为构建环境,在从节点上执行持续集成配置脚本。配置脚本调用代码检测与软件构建相关的工具,实现环境清理、代码静态审查、软件编译、自动化测试、代码覆盖率检测和软件发布等操作。脚本执行完成后,将构建结果输出到指定目录,供持续集成服务器读取和分析。持续集成服务器通过配置插件、读取构建和测试日志,将结果可视化输出到web端界面。整个过程的实现主要依赖于配置脚本,通过修改配置脚本可以实现自定义流程裁剪和定制。持续集成平台设计方案见图3。
2.3 持续集成和测试方案的实施
选用Jenkins作为基础持续集成服务器。与其他持续集成工具相比,Jenkins主要有2个优点:一是易于安装配置,提供直观灵活的web用户界面,便于配置管理;二是具有强大的插件机制,可以显示测试结果和构建日志等反馈信息。[11-12]版本控制工具使用Subversion,用于存储、追踪目录和文件的修改
历史。软件包管理工具使用Conda,用于管理软件依赖关系,可有效处理软件产品之间的冲突。自动化测试工具使用自主研发的AutoBenchTest(简写为ABTest),适用于数值模拟软件测试算例的串行和并行执行,能够自动生成测试报告和结果统计报表。
基于以上设计方案和支撑工具,该平台具体实现过程如下。
2.3.1 基于Docker容器技术配置构建环境
采用Docker容器技术为持续集成服务器提供构建环境。在Docker中构建容器时,通过编写Dockerfile脚本实现容器的快速生成。该Dockerfile包含创建镜像所需要的全部指令,实现对网络、访问端口、编译器、构建环境、版本控制服务和其他依赖软件的安装配置。基于该Dockerfile文件,仅执行docker build命令即可一键式创建镜像,同时自底向上打包软件及其构建环境。[13]这种方式能够减少镜像和容器的创建过程,简化部署、方便系统升级。
容器搭建完成后,持续集成服务器可以通过任务配置的方式选取相应的Docker容器作为构建环境执行软件编译与测试。[14]当任务执行完成后,持续集成服务器生成容器并保存至Docker镜像仓库,便于后期环境恢复和错误定位。基于Docker的环境配置方案见图4。
2.3.2 基于Conda工具实现自动化构建
Conda工具的实现机制主要包括远程服务器端和本地端2部分。对于远程服务器端来说,产品发布平台主要用于统一管理所有软件构建所依赖的公共库、第三方软件和工具软件等,以减少重复构建的操作。对于本地端来说,面向数值模拟软件的构建和打包需求,可支撑软件完成依赖解析和软件编译,最终生成二进制安装包。
本地端的构建自動化通过编写Conda配置文件meta.yaml和build.sh脚本实现。build.sh是自动化编译脚本,用于记录软件编译步骤、需要设置的环境变量信息等内容。该脚本是在程序原有的CMakelist/ Makefile上进行一层封装,不会对程序原有编译方式造成影响。对用户来说,该工具的使用和维护成本较小。meta.yaml提供指定远程源路径、安装包名称、版本、源码目录、编译/运行时所依赖的软件和版本等内容。明确以上关键信息后,Conda工具通过读取配置文件解析软件依赖关系,从远程软件源获取安装包并配置构建环境,完成编译并生成二进制安装包。
2.3.3 编写持续集成配置脚本
持续集成配置脚本基于shell语言与Jenkins Pipeline语法编写,主要包括版本检出、代码静态检查、软件编译、验收测试、覆盖率检测等5个部分。该脚本按照流程分阶段组织,每个阶段完成相应的环境清理、工具调用、测试数据输出、输出数据处理和可视化等操作。
此外,脚本尽可能地使用特定变量和相对目录,规避不同软件之间的个性化差异,从而形成持续集成配置脚本模板,可支持构建任务的快速创建。
2.3.4 基于Jenkins插件反馈构建结果
Jenkins提供丰富的二次开发接口和插件机制[15],能够支持静态审查、代码量统计、自动化测试和测试覆盖率结果可视化等操作,可直观地向测试人员反馈评测结果。
在插件管理界面安装Cppcheck和Sloc插件,在配置界面填写输出文件目录和文件格式等关键信息,读取并分析XML形式的输出文件,对结果进行统计、分类并输出详细日志,完成静态检查和代码量统计。以代码静态审查为例,其不仅能够简明扼要地反馈错误统计结果,而且能够显示错误详细信息,包括静态审查错误文件、行数、错误类型和日志等信息,便于研发人员及时解决程序中潜在的数组越界、内存泄漏等问题。静态审查错误日志实例见图5。
在软件测试和覆盖率统计方面,基于持续集成服务器提供的Publish Html插件,在配置界面明确测试报告生成目录、网页文件名称和标题等,Jenkins可将任务与工具生成的Html界面关联,并在任务主界面显示测试算例执行报表、测试覆盖率检测结果等。自动化测试报告实例见图6。报告中明确给出测试环境信息、测试算例执行状态和统计信息,提供具体算例的执行日志,便于定位错误。测试覆盖率检测报告实例见图7。报告中不仅统计本次软件测试中整体代码行数与函数覆盖率情况,而且能够通过颜色明确标识具体代码行的执行信息,便于研发人员进一步完善测试算例。
3 应用效果
该持续集成平台用于支撑中物院高性能数值模拟软件中心的产品化和应用推广工作。该平台可实现产品构建、测试和发布工作的自动化,已应用于35款数值模拟软件,完成2 100余例测试算例自动化测试,发布软件产品3 000余次,产品交付周期相比之前缩短约75%,大幅提升产品构建与交付效率。
基于Dockerfile容器模板,该平台可支持构建环境的快速生成。目前,构建环境覆盖Centos、Redhat、Fedora和Suse等多种操作系统、编译器和MPI版本,能够满足银河、天河2号等典型高性能计算环境的产品部署需求。在产品发布后,用户可一键式安装部署,平台自动解析软件依赖和安装与环境变量配置,降低软件产品部署难度和使用成本。
此外,针对软件研发过程中的问题记录和反馈需求,该平台可实现构建和测试日志全面输出。对于单个软件的构建来说:一方面,该平台能够直观地反馈阶段执行情况,记录整个构建任务中的操作步骤和报错日志,并可视化输出各个工具生成的数据文件;另一方面,该平台能够对测试结果进行统计分析,生成构建过程趋势图(见图8),有效监控软件开发过程数据,促进产品质量持续提升。
4 结束语
基于Docker与Jenkins技术设计并实现面向数值模拟软件的持续集成平台。该平台从数值模拟软件面临的实际应用需求出发,建立代码静态分析、依赖关系解析、软件编译、测试和部署等自动化工作流程,实现构建环境的快速搭建和配置管理,详细记录软件构建日志和测试结果,便于研发团队及时发现软件缺陷、快速分析定位问题。
该平台可大幅度缩短产品构建、发布和交付周期,有效保障数值模拟软件的产品化和推广应用。但是,该持续集成平台未采用数据库技术对测试数据统一管理。在下一步工作中,将深入开展测试数据管理和分析工作,记录产品质量变化趋势,及时发现软件中潜在的缺陷。
参考文献:
[1] 莫则尧, 裴文兵. 科学计算应用程序探讨[J]. 物理, 2009, 38(8): 552-558. DOI: 10.3321/j.issn:0379-4148.2009.08.004.
[2] 田鸿运, 刘青凯, 成杰, 等. 一种面向高性能数值模拟软件的自动化测试平台[J]. 计算机工程与科学, 2017, 39(11): 1980-1985. DOI: 10.3969/j.issn.1007-130X.2017.11.002.
[3] 蒋祥刚. Make与Makefile初探[J]. 中文信息, 2002(8): 62-65.
[4] HOFFMAN B, COLE D, VINES J. Software process for rapid development of HPC software using CMake[C]// Proceedings of 2009 DoD High Performance Computing Modernization Program Users Group Conference. San Diego: IEEE Press, 2009: 11873937. DOI: 10.1109/HPCMP-UGC.2009.62.
[5] KAWALEROWICZ M, BERNTSON C. Continuous integration in .Net[M]. New York: Manning, 2011.
[6] HATCHER E, LOUGHRAN S. 使用Ant进行Java开发[M]. 北京: 电子工业出版社, 2005.
[7] 董晓光, 喻涛. 使用Maven构建Java项目[J]. 电子技术与软件工程, 2014(10): 105.
[8] BERGLUND T, MCCULLOUGH M. Building and testing with Gradle[M]. Boston: O′Reilly Media, 2011.
[9] 陈能技, 付勇, 等. 大规模组织DevOps实践[M]. 北京: 电子工业出版社, 2018.
[10] 成奋华, 金敏. 基于敏捷过程的IT项目范围管理的研究与应用[J]. 计算机技术与发展, 2010, 20(10): 232-236. DOI: 10.3969/j.issn.1673-629X.2010.10.056.
[11] HUMBLE J, FARLEY D. Continuous delivery: Reliable software releases through build, test, and deployment automation[M]. Alaska: Addison-Wesley Professional, 2010.
[12] DUVALL P M, MATYAS S, Glover A. 持續集成软件质量改进和风险降低之道[M]. 北京: 电子工业出版社, 2012.
[13] MERKEL D. Docker: Lightweight Linux containers for consistent development and deployment[J]. Linux Journal, 2014, 2014(239): 2.
[14] 张兆晨, 罗铁坚. CCI: 一种基于容器化的持续集成系统[J]. 中国科学院大学学报, 2018, 35(4): 569-575. DOI: 10.7523/j.issn.2095-6134.2018.04.021.
[15] 刘巧玲, 范冰冰, 黄兴平. 基于Hudson的持续集成研究和应用[J]. 计算机系统应用, 2010, 19(12): 151-154.
(编辑 武晓英)