背景

公司研发团队AB两市异地协作,源码服务器在B,构建服务器也在B。A的同胞们需要得到完整的产品包需要等待B的构建服务器构建完产品后ftp上传到A的一个服务器上 。由于网络问题,通常需要等待1小时甚至更长的时间A才能得到最新的产品包。这就造成了A研发同事处理某些问题会滞后很多。

早期处理

2年前终于有人无法忍受不能及时获取到产品包处理客户问题。因此提出了在A市购置一台构建服务器,和B市服务器分别进行构建。

由于更新源码是增量的,每次仅需要从B市获取最近改动过的代码即可进行构建并且构建的时间远小于网络传输产品包的时间。因此A市的滞后问题得到了大幅减少,现在仅需要20分钟左右进行构建即可得到产品包。

但是这样也存在问题,由于是不同的服务器构建,因此两地的产品包很难保持一致。

新的处理方案

本次大版本启动,引入了一系列的项目管理方案,加入了单元测试、静态代码分析等,构建时间大幅增加。老的构建模式已经不大适用了。

因此顺便也改造了整个构建流程。

构建流程

工程使用maven管理。为了支持各功能模块实现独立发布,进行了各工程间解耦,使用接口进行交互。 新的构建流程大约是这样的

平台构建->按需构建模块并执行单元测试->各模块聚合->打包完整的产品

新的构建,老的同步方案

就两地都能在最短的时间内获取到最新的完整产品包,重新评估了下之前的两种构建方案:

  • 由于构建时间增加,网络传输完整的产品包已经和构建时间差不多。该方案简单方便,仅需执行一次ftp上传即可。
  • 依然进行两地分别从源码服务器取得源码后使用相同的流程配置进行构建。该方案依然比拷贝产品包优势,因为上班时间网络状况比较差,最多的时候甚至3个小时没能拷贝完成产品包。

新的构建,新的同步方案

然而两种方案都会让A地的人员在B地有完整产品包以后1个小时以上才能得到产品包,因此都无法接受。

我们分析下A、B两种方案的优势:

  • A方案不需要进行一次多余的构建流程
  • B方案可以进行增量更新,网络传输量小

为了不需要进行一次多余的完整构建,也可以增量更新,经过考虑,使用了一种新的方案。

将同步的内容从源码变为编译聚合后的代码,B的服务器将构建过程中产生的最终产品文件在打包前全部同步到A的构建服务器上,A仅需要执行打包操作即可。

新方案的具体实施

构建环境

使用Jenkins作为CI工具,A、B两市分别一台linux服务器,源码服务器依然在B市。

执行流程

在B的Jenkins上增加一个rsync任务,其流程位于各模块聚合后,产品打包前。

其内容就一个shell命令,将2地linux服务器的构建文件夹同步(两个linux服务器需要建立ssh信任,不然需要录入账号密码)。

rsync -az --delete -progress -e ssh $buildDir $user@$remoteServer:$buildDir

rsync命令用于linux间同步,我们使用-az来保持所有文件的属性也进行同步,–delete删除B服务器上存在而A服务器上不存在的文件。

除了第一次同步需要较多时间外,往后每次同步都只会更新修改的文件,只需要很少的时间。

现在两地都有相同的完整产品文件了,只需要分别对文件进行打包就行了。

我们在A的Jenkins上配置一份和B的jenkins上打包流程相同的任务即可。然后使用* Parameterized Remote Trigger Plugin * 插件在B的jenkins执行完同步任务后进行远程触发A的jenkins上的打包任务。

如无法在A的jenkins打包任务中配置出构建相同的包名,也可以在B的触发任务中将包名作为参数进行传递到A的打包任务中。

结果

经测试,使用新方案后,平均同步时间能缩到到30秒左右。 由于打包是基本上同步进行,因此两地都能在大约相同的时间得到产品包,并且能保持两地的产品包内容完全一致。