并发执行——时间就是金钱,资源也是金钱
实际问题
尽管我们将整个持续集成过程中所需完成的工作根据具体任务分成了很多独立的步骤,并管道化运行,但是并未能解决真正的“时间运行超长”问题。因为,我们的测试代码已经达到相当数量,运行一次所有的单元测试要在40分钟以上,而在一台机器上运行所有功能测试大约需要2小时以上。而且可以预见到,这一时间量会快速增加。那么,要如何解决这个问题呢?当然不可能因为时间长而不增加测试。
理论基础
将同一类型的测试分成几组,同时运行在配置相同的Agent上。这样,虽然不能减少总时间,但是完成所有同类型测试所需要的时间周期会缩短。
解决方案
Cruise团队成员利用业余时间创建了一个开源项目,名为Test-Load-Balance,利用Cruise的特性,根据Cruise中Job的配置,自动将测试分成多组,运行于不同的Agent中。当测试运行时间到了无法接受的时候,只需要在 Cruise的配置文件中增加一个Job,它就会自动感知这一变化,将测试再多分一份出来。只要有足够的Agent,那么你的测试时间一定会缩短到15分钟以内。目前,Cruise的单元测试被Test-load-Balance自动等分成四组运行于Windows,以及五组运行于Linux,而功能测试也一样被自动分成四组,分别运行于Windows和Linux。目前用于 Cruise持续集成环境中的工作站共计11台虚拟机,使Cruise的所有单元测试可以在15分钟内完成,所有的功能测试可以在35分钟内完成。
我们的持续集成基本结构变为:
图8 Build Cloud
Cruise团队的持续集成类似下面的配置文件:
<pipeline name="Cruise"> <stage name="UnitTest"> <job name = "windows-01"/> <job name = "windows-02"/> <job name = "windows-03"/> <job name = "windows-04"/> <job name="linux-01"/> <job name="linux-02"/> <job name="linux-03"/> <job name="linux-04"/> </stage> <stage name="FuncTest"> <job name = "windows"/> <job name="linux"/> </stage> <stage name="TwistTest"> <job name = "windows-01"/> <job name = "windows-02"/> <job name = "windows-03"/> <job name = "windows-04"/> <job name="linux-01"/> <job name="linux-02"/> <job name="linux-03"/> <job name="linux-04"/> </stage> <stage name="Package"> <job name = "Solaris"/> <job name="linux"/> </stage> <stage name="UAT"> <job name = "deployUAT"/> </stage> <stage name="Production"> <job name = "deployProd"/> </stage> </pipeline> |
利弊分析
我们已无需投入过多的精力在持续集成环境上了,除非我们的硬件不足(可现在的硬件成本要比人工成本低多了)。因为Cruise Server自动会将构建计划平均分成多组,并分配到相应的工作站(Agent)上运行。如果测试代码进一步膨胀,我们只需要在相应的测试阶段加增加 Job的个数,再克隆出几台虚拟机扔到我们的Agent grid中。而这仅需很少的人工操作,根本不必修改我们的自动构建代码。