24岁秃头程序员教你微服务交付下如何持续集成交付,学不会砍我

微服务如何持续集成交付

在微服务架构下,每一个微服务都是职责单一的,可独立部署单元,但是众多分散的微服务也带来了代码共享、微服务功能依赖、版本管理等复杂问题,微服务需要解决配置管理、服务持续集成、持续部署、快速交付过程中的一系列软件挑战。下面我们将讲解如何通过配置管理、持续集成、持续交付为微服务保驾护航。

配置管理概述

微服务架构下,应用被拆分为众多细粒度服务,对统一的配置管理的需求也随之增加。软件配置管理(Software ConfigurationManagement,SCM)指通过执行版本控制、变更控制的规程,以及使用合适的配置管理软件,来保证所有配置项的完整性和可跟踪性。软件配置管理在整个软件生命周期中建立和维护项目产品的完整性,它的目标如下。

  • 目标1:对软件配置的各项工作进行计划。

  • 目标2:被选择的项目产品得到识别、控制并且可以被相关人员获取。

  • 目标3:已识别出的项目产品的更改得到控制。

  • 目标4:使相关组别和个人及时了解软件基准的状态和内容。

软件配置项在配置管理流程中,IT组件及运用这些IT组件所提供的服务被称为软件配置项(SCI)。软件配置项包含了软件代码、代码的版本描述、文档数据(开发人员、用户)、软件所属组织等所有软件生产过程中产生的数据。这些配置项可以作为元数据信息对外暴露数据接口,其他第三方平台可以根据这些配置项的元数据信息调整系统中的相关配置。

配置管理数据库(CMDB)

配 置 管 理 数 据 库 ( Configuration Management Data Base ,CMDB)的官方解释是,它用来存储与管理企业IT架构中设备的各种配置信息,包含了配置项全生命周期的信息及配置项之间的关系。CMDB开放的数据服务供各个业务系统调用,从而让业务系统具备统一的视图和配置信息。

其实微服务在自动化运维、标准化运维、DevOps中都离不开CMDB,可以说CMDB是运维体系的基石。有了配置信息数据库,后面各种标准、流程都可以建立在CMDB基础之上,实现真正的标准化、自动化、智能化运维,在节约运维成本的同时,降低运维流程混乱带来的操作风险。

基线

在开始软件项目开发前,我们需要一个稳定的代码版本。我们将这个稳定的代码版本称为代码基线,基线是软件进一步开发的基础,同时基线的确立是软件项目中的一个里程碑。当基线形成后,项目负责SCM的人需要通知相关人员,并且告知在什么位置可以找到基线的代码版本,这个过程可被认为是内部发布。至于对外的正式发布,更是应当从基线的版本中发布。下面总结一下基线配置的优势。

  • 制定基线可以让所有开发人员的工作在基础代码层面保持一致和同步,为开发工作制定一个基点和快照。

  • 制定基线可以让项目之间建立前后继承关系,而不会因为各自代码的基线不一致,导致无法追溯变更。

  • 当代码变更有问题或者不可靠时,基线为分支代码提供了一个取消变更或者回退版本的操作。

在微服务架构中,基线模式通常把框架下的某个版本作为代码基线。以Spring Boot代码为例,Spring Boot的快速迭代,出现了众多版本。从Spring Boot 1.x到Spring Boot 2.x,不同的版本配置,让Spring Boot对依赖配套的底层组件和类库都有很大的差异。如果我们在开发过程中,没有统一的代码基线,在后续微服务的开发集成过程中,将出现代码版本冲突的风险及类定义缺失等底层代码不兼容问题。对于Spring Boot的版本兼容问题,我们可以参考官方网站发布的Release说明。

持续集成概述

持续集成(Continues Integration,CI)最早在1991年由GradyBooch命名并提出。XP极限编程中采用了CI的概念,并提倡每天不止一次集成。当时持续集成的目的就是能够通过采用自动化的手段和工具,来代替手动处理事务,实现项目的持续集成。而提出微服务概念的软件大师Martin Fowler对持续集成的定义则更加准确。

持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化构建(包括编译、发布、自动化测试)来验证,从而尽快地发现集成错误。

在微服务架构下,我们关注更多的是如何将一个大的单体拆分成多个微服务。分而治之虽然解决了系统的耦合问题,但是就像汽车的零部件被拆解后,如何再组装成一个完整的汽车一样,微服务同样需要通过相关调用、相互依赖、系统集成,最终完成整体对外功能。而持续集成正是将各个微服务的功能集成在一起来整体对外提供服务的。

同时,持续集成必须考虑针对这些独立部署的微服务,如何建立起代码仓库中的代码版本与CI构建和交付物版本之间的对应关系。在代码被更新后,保证每一次迭代和构建都可以经过质量验证,回归测试用例如何自动化执行,代码的频繁更新需要有一个良好的持续集成

方案来高效地验证,并控制变更代码的副作用(Side-Effect)。

持续集成Pipeline

下图是持续集成的一个Pipeline(管道)方案,里面包含了我们通常会使用的代码集成工具和最佳实践。下面我们对持续集成使用的工具一一进行介绍。

Git代码构建

在微服务架构下,我们通过代码集成到主干分支完成一次CI构建,代码分支管理有多种不同的构建模式,具体如下:

  • 单独代码库,一个CI构建:在这种方式下,微服务使用相同的代码库,并且使用一个单独的CI构建,这种模式容易产生代码冲突,一般不建议采用。

  • 单独代码库,多个CI构建:这种模式通过创建多个子目录,每个子目录由单独的CI构建,这种模式在实际开发场景中使用较多。这种方式的问题是所有微服务代码都在相同的代码库,存在服务代码耦合隐患。

  • 多个代码库,多个CI构建:每个微服务都有自己独立对应的代码库,这使微服务更加独立,代码管理更加独立。但缺点是跨服务的共享代码修改变得复杂,需要将共享代码上传到私服,通过版本工具进行代码升级更新。

对于使用传统SVN或者CVS的代码库构建的项目,使用第二种模式比较常见;而把Git作为代码库,划分为多个代码库则更适合管理,相比传统单一代码库,集成过程中产生代码冲突的可能性会大大降低,也降低了集成代码过程中处理冲突花费的精力和成本。

如果你的微服务使用了单一代码库和多个CI构建的模式,为了降低集成的风险,建议提高本地代码提交到主干分支的频率,减少由于代码变化过大引起的集成风险。

Maven构建&Nexus私服

在Spring Boot项目中,大部分公司目前还是以Maven作为主要的代码编译工具。Maven工具的安装十分简单,IDEA和Eclipse工具对Maven都有相应插件的支持。这里我们主要介绍Maven中的pom.xml文件。

最基本的pom.xml文件包含工程信息、Spring Boot父工程、属性配置、依赖包、构建插件。下面是pom.xml文件的一个简单模板。

下面是微服务Spring Boot应用依赖关系管理的示意图。

  • 最上层Spring Boot Parent:只有pom.xml文件,无代码。

  • 中间层继承Parent依赖:包含pom.xml文件和一些具有通用性的代码,如工具类等。

  • 最下层应用:Spring Boot应用工程,含有启动类,与单体应用类似。

Nexus私服管理

为避免在微服务下滥用包,应该统一管理第三方依赖的版本,同时为了方便mvn deploy操作,可以加上公司内部Maven私服的信息。

首先,执行代码上传私服命令。Maven私服常用的操作是将代码库安装到本地,并推送到Maven私服,代码如下:

其次,在项目pom.xml中设置的版本号添加Snapshot标识的都会发布为Snapshot版本(快照版),没有Snapshot标识的都会发布为Release版本。Snapshot版本会自动增加一个时间戳作为标识。如1.0.0-SNAPSHOT 发 布 后 变 成 
1.0.0-SNAPSHOT-20180522.123456-1.jar,需要注意的是,Snapshot作为开发过程中使用的快照版是最为方便的,它可以随时更改代码,并重新被上传到Nexus。而Release发行版不能更改代码,如有修改提交失败,或因为版本冲突,则需要为Release指定新的版本号。下面我们对比下Snapshot与Release的区别。

  • nexus-releases:用于发布Release版本。

  • nexus-snapshots:用于发布Snapshot版本。

Release版本与Snapshot版本的定义如下。

  • Release:1.0.0/1.0.0-RELEASE.

  • Snapshot:1.0.0-SNAPSHOT.

在分发到远程Maven仓库之后,所有能访问该仓库的用户都能使用你的组件,然后我们需要配置pom.xml的distributionManagement来指定Maven分发构件的位置,在pom.xml中添加如下代码实现远程仓库的配置功能。

注意:虽然目前Maven仍然是Java代码构建的事实标准,但是Groovy的Gradle构建工具相比Maven摒弃了冗长的XML语法格式,同时在集成Maven诸多优点的前提下,Gradle在并行编译和编译效率方面都有更好的体验。在Spring Boot 2.3.0中,Spring Boot开始使用Gradle而非Maven进行构建。而Spring Boot团队给出的切换到Gradle的主要原因是减少构建所需要的时间。对于Spring Boot构建的复杂性,Gradle的构建缓存能力,以及增量和并行构建都是模块化CI构建中加快构建速度的重要因素。

测试验证

在持续集成中,当代码提交到主干分支后,需要单元测试、集成测试、功能测试。对于微服务而言,频繁的代码发布和快速迭代需要一个自动化回归测试方案,帮助验证增加的代码改动是否有副作用。

在系统集成测试中,对于一些依赖上下游服务的测试验证工作,还要模拟对端服务的API,这种方式就是俗称的“挡板测试”,其实就是Mock程序,用于客观条件限制下,在无法搭建整体测试环境的情况下,使用软件系统模拟依赖的服务功能。常见的使用场景是,当真实的调用可能产生资费时,就需要挡板技术解决系统集成时的代码验证问题。

下面我们使用JUnit实现Spring Boot程序的单元测试功能,从Spring Boot 2.2.0开始引入JUnit 5作为单元测试默认库。

Spring Boot 2.2.0 之 前 , spring-boot-starter-test 包 含 了JUnit 4的依赖,Spring Boot 2.2.0之后替换成了JUnit Jupiter。下面的实例用来演示使用Spring Boot整合JUnit的单元测试。

1. 创建项目,添加Maven依赖

2. Dao层实例代码

3. Service层实例代码

4. 编写启动类

5. 编写测试文件,运行testSaveUser方法即可

6. 执行mvn clean install会自动触发JUnit测试工作,测试结果会输出到Console

代码静态检查

SonarQube是一个用于代码质量检测管理的开放平台,SonarQube可以通过不同的插件对这些结果进行再加工处理,通过量化方式度量代码质量的变化。SonarQube不仅提供了对IDE的支持,可以在Eclipse和IntelliJ IDEA这些工具里联机查看结果;同时对大量的持续集成工具提供了接口支持,可以很方便地在持续集成中使用。另外,SonarQube的插件还可以对Java以外的其他编程语言提供支持。

  • 编码规范:是否遵守了编码规范,遵循了最佳实践。

  • 潜在的BUG:可能在最坏情况下出现问题的代码,以及存在安全漏洞的代码。

  • 文档和注释:过少(缺少必要信息)、过多(没有信息量)、过时的文档或注释。● 重复代码:违反了Don't Repeat Yourself原则。

  • 复杂度:代码结构太复杂(如圈复杂度高),难以理解、测试和维护。

  • 测试覆盖率:编写单元测试,特别是针对复杂代码的测试覆盖是否足够。

  • 设计与架构:是否高内聚、低耦合,依赖最少。

在Jenkins中下载SonarQube插件,安装完成后,在系统管理->系统设置中,找到SonarQube servers模块,填写需要扫描的工程代码路径,构建成功后即可在SonarQube地址中登录访问,查看代码扫描情况。

Jenkins实现自动化集成

Jenkins是一个持续集成工具,也是我们持续集成整个流程的主角,从Git源码库中的代码拉取、单元测试验证到代码扫描报告的一系列流程,都可以通过Jenkins实现自动化执行。它可以根据设定持续定期编译,运行相应代码;运行UT或集成测试;将运行结果发送至邮件或展示结构。

目前,在现有的持续集成工具中,Jenkins已经成为持续集成事实上的标准,Jenkins的Pipeline插件已经定义了这些标准过程。

Jenkins用Java编写,可在Tomcat等流行的Servlet容器中运行,也可独立运行。通常与版本管理工具、构建工具结合使用;常用的版本管理工具有SVN、Git,构建工具有Maven、Ant、Gradle。Jenkins的安装和初始化启动过程可以参考Jenkins官网。

下面是使用Docker构建Jenkins的CI Server的过程。

首先,制作Jenkins的DockerFile配置文件。

其次,构建Jenkins Docker Image。

然后,启动Jenkins CI容器服务。

使用Docker部署Jenkins的好处是应用程序可以发布并直接部署Docker镜像,省去大量环境配置。我们在后面的Docker交付中,将对基于Docker的交付模式做进一步讲解。

下面,我们总结一下使用Jenkins实现持续集成的流程。

(1)开发者将自己分支的最新代码推到主干分支。

(2)从Git Master分支收到新的代码提交后,会触发Webhook启动相应的Jenkins job,启动Jenkins的整个CI流程。

(3)Jenkins从对应项目设置的代码仓库拉取相应编译环境的代码,完成代码的编译。

(4)Jenkins根据Pipeline插件功能增加集成测试任务,用于自动化回归测试。

(5)Jenkins根据事先设置的脚本任务和集成的SonarQube插件,完成对指定项目的代码扫描和代码分析报告,并将结果发送到指定邮箱。

下面是利用Jenkins的Pipeline DSL代码描述持续集成的示例流程。

总结一下,上述过程原本需要开发人员手动切换到不同环境进行例行工作,现在通过Jenkins实现了常规化、自动化的持续集成工作,有效避免了开发人员集成代码的重复工作。上述工作完成后,就实现了从代码提交到代码集成编译、单元测试、代码检查相关的集成工作。利用其Pipeline式的管理方式,Jenkins不仅可以进行持续集成,还可以进一步实现后续的代码部署和交付任务。

持续交付概述

持续交付(Continuous Delivery,CD)是一种软件工程方法,开发者可以用快速、自动化和可重复的方式从源码库部署交付软件,确保交付过程的标准化和自动化。它更加注重随时随地提供可靠发布的能力。

如果说持续集成是让我们的团队通过快速迭代提交代码到共享代码库中,提前发现模块集成中的问题,那么持续交付就是通过构建自动化的交付平台,允许团队更加频繁地交付可工作的软件产品,从而能够更快地得到用户对产品的反馈和对产品价值的体验。

持续交付最早由Jez Humble和David Farley提出,并在《持续交付:发布可靠软件的系统方法》一书中对其实现进行系统说明。而本书未对持续交付做明确定义,目前对持续交付比较认同的定义来自DevOps Handbook上的定义。

持续交付指的是,所有开发人员都在主干上进行小批量工作,或者在短时间存在的特性分支上工作,并且定期向主干合并,同时始终让主干保持可发布状态,并能做到在正常工作时段里按需进行一键式发布。开发人员在引入任何回归错误时(包括缺陷、性能问题、安全问题、可用性问题等),都能快速得到反馈。一旦发现这类问题,就立即加以解决,从而保持主干始终处于可部署状态。

首先,微服务的流行本身就是在持续交付方法论下发展起来的。

在单体架构下,所有模块集成在一个代码库下,往往一个小的改动会牵一发而动全局,代码的耦合影响产品对外的发布交付速度,如果不进行微服务的拆分,则系统的持续交付将面临一系列问题,而将单体分解成独立、自治、可部署的微服务,单独交付部署,就可以减少代码之间的耦合及相互影响。同时,微服务的交付周期短、功能单一、扩展性好、技术多样性等特征,都是持续交付所需要的。

同时,微服务的发展需要持续交付的支撑,微服务在拆分后面临服务众多、版本众多的问题,如果没有一套自动化的代码构建、测试、部署打包工具,则很难应付微服务在规模化部署下的持续交付。

另外,持续交付的价值不仅仅在于提升服务交付的效率,它还通过指定统一的标准、规范的流程、自动化平台,影响着软件研发到运维的整个生命周期。而持续交付最终将软件的研发流程进化为DevOps软件开发模式,实现端到端的软件价值交付。

持续交付Pipeline

下面是持续交付Pipeline的流程图。可以看出,持续交付的前提是持续集成,也可以说持续交付包含持续集成过程。

持续交付的核心是构建一个自动化的流水线,而这个持续交付工作平台可能贯穿了软件项目的整个生命周期。它不仅要串联起软件工程代码的提交集成、测试验证、打包管理、镜像交付,同时将影响整个公司组织端到端的业务,从开发测试到部署交付的整个流程过程。

下面我们总结一下实现持续交付的核心工作流程。

  • 准备工作

  • 集成工具的技术选型,在持续集成一节中,源码的管理、持续集成工具的选择、自动化测试等软件工具的选择都将是后续完成自动化流程的关键步骤。

  • 部署载体的选择,目前容器已经成为微服务部署实施的标准运行时环境,而对于有状态服务或者存储相关服务,我们需要提前规划好交付方式的步骤。

  • 软件工程和组件结构可以帮助更频繁地发布服务,而不会对用户产生影响。

  • 软件监控和服务治理是持续交付的重要机制,在构建持续交付平台前,就应该为服务运维中需要的日志管理、应用及容器状态、指标性能等需求做配套设计开发。

  • 组织结构、业务流程的变化,需要支持持续交付。

  • 自动化一切

  • 自动化的代码构建和打包。

  • 自动化的测试集成。

  • 自动化的发布机制。

  • 测试环境下服务的自动化部署。

  • 生产环境下服务的自动化部署。

  • 构建持续交付流水线

我们在持续集成中,说过利用Jenkins的Pipeline可以实现自动化的流水线流程。如果你所在公司的人力不是很充足,则可以使用开源版本的Jenkins构建流水线平台。对于定制化的流水线,我们可以把软件生命周期中从代码到生产环境的所有过程全部可视化地展示出来,实现端到端的持续交付,实现持续交付过程中的增强功能。

  • 实现环境定制化配置管理。

  • 实现版本的回滚。

  • 实现灰度发布和版本切换。

  • 记录操作日志审计。

  • 可以实现网络的监控和拓扑管理。

本文给大家讲解的内容是微服务交付:微服务如何持续集成交付?

  1. 下篇文章给大家讲解的内容是微服务交付:基于容器的交付-Docker概述
  2. 觉得文章不错的朋友可以转发此文关注小编;
  3. 感谢大家的支持!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值