专栏名称: CSDN
CSDN精彩内容每日推荐。我们关注IT产品研发背后的那些人、技术和故事。
目录
相关文章推荐
新浪科技  ·  【#极越中层曝夏一平管理内幕# ... ·  4 天前  
新浪科技  ·  【#董宇辉近日成立3家新公司#】天眼查App ... ·  6 天前  
36氪  ·  留给杨植麟「排雷」的时间不多了 ·  6 天前  
51好读  ›  专栏  ›  CSDN

Yelp是如何做到每天运行成千上万个测试

CSDN  · 公众号  · 科技媒体  · 2017-05-19 12:42

正文

作者 | Chunky G. 

翻译 | 贺雨言


快速进行功能开发对企业至关重要,开发团队都试图通过减少测试、配置和监控变化的时间来提高开发人员的效率。为了让开发人员安全地敲代码,Yelp使用内部分布式系统Seagull运行2000多万个测试。



什么是Seagull?


Seagull是一个容错和故障恢复的分布式系统,用来并行执行测试包。Seagull由以下几部分组成:


  • Apache Mesos(管理Seagull集群上的资源)

  • AWS EC2(提供组成Seagull和Jenkins集群的实例)

  • AWS DynamoDB(存储调度器的元数据)

  • Docker(隔离测试需要的服务)

  • Elasticsearch(追踪测试运行次数和集群使用数据)

  • Jenkins(搭建代码项目并运行Seagull调度器)

  • Kibana和SignalFx(提供监控和报警)

  • AWS S3(为测试日志提供真实数据来源)


挑战


在准备单片Web应用和Yelp主机配置新的生产代码之前,Yelp开发人员在特定的主机上运行整个测试包。测试前,开发人员需启动用来调度集群测试的Seagull。以下两点需要着重考虑:


1. 性能:每个Seagull-run包含将近10万个测试,依次运行完毕需要大约2天时间。

2. 规模:通常一天有300多个seagull-runs在运行,高峰时段要同时运行30-40个测试。


这项任务的挑战在于执行每一个Seagull-run所花费的时间是以“分钟”而不是以“天”来计算,同时保证在这个时间段内成本效益好。


Seagull怎样运作?


首先,开发人员在控制台启动Seagull-run,即启动Jenkins搭建代码项目并生成测试列表。然后,将测试打包传给Seagull集群上的调度器进行测试。最后,将测试结果存储在Elasticsearch和S3中。



1. 开发人员为特定的代码版本(基于其分支git SHAs)启动Seagull-run,设git分支为test_branch。


2. 生成test_branch的代码项目和测试列表并上传到S3。


3. Bin Packer抓取测试列表和测试的历史时序元数据,从而构建包含测试的多包。有效打包是一个装箱问题,可以用以下两个算法解决,(选择哪种算法)取决于研发人员传给Seagull的参数:


  • 贪婪算法:首先根据历史测试时长将测试分类,然后将测试时长设置为10分钟的测试归档。

  • 线性规划(LP):为了防止相关测试,一个测试需要和另一个测试在同一个包里运行。因此,我们使用LP进行打包,LP方程的目标函数和约束条件定义如下:


  •     目标函数:对生成的包总数取最小值

  •     主要约束条件: 


    • 单包的测试时长少于10分钟;

    • 一个测试只能放入一个包;

    • 相关测试放入同一个包。


我们使用Pulp LP解算器求解方程:



其中,bundle和test_bundle是LP变量,max_bundles和bundle_max_duration是整数。

通常,在LP约束条件中,我们会考虑测试用例的搭建和解除的时长,但是为了简便,在这里我们忽略不计。


4. 在Jenkins主机上启动调度器进程,Jenkins主机抓包然后搭建mesos架构。我们为每一个Seagull-run创立一个新的调度器。每一次运行生成300多个包,将运行时长在10分钟左右的包归为一类。调度器为每一个包建立一个Mesos执行器,只要Mesos控制器提供充足的资源,就将Mesos执行器列入Seagull集群时间计划表。

 
5. 一旦执行器被列入到集群,执行器内部将进行以下步骤:



每一个执行器建立一个沙箱,从S3(在步骤(2)中已上传)下载新建项目。然后下载对应于相关测试服务的Docker图片就可以建立Docker容器(服务)了。当所有的容器都启动并运行,就开始进行测试了。最后,测试结果和元数据存储在Elasticsearch(ES)和S3中。我们用内部代理服务Apollo写入ES。


如果你生活在一个分布式系统的世界,你一定无法避免主机故障。Seagull对任何实例故障都具有容错功能。



例如,假设一个调度器要运行两个包。Mesos会提供一个代理(A1)的资源给调度器。假设调度器认为资源充足,那么这两个包会被安排在A1上。假如出于某种原因,A1出故障了,那么Mesos会通知到调度器。调度器的任务管理器决定重试或者丢弃那两个包。如果重试,当Mesos下一次提供充分的资源(这种情况下,是提供代理A2的资源)时,那两个包会被重新安排到时间计划表里。为了防止包被丢弃,调度器会将那两个包测试标记为“未执行”。 


6. Seagull UI用Apollo从ES获取结果,并将结果加载到UI供开发人员查看。如果结果全部通过,就可以准备配置了。


规模化挑战


为了确保测试包的及时性,尤其是在高峰期,Seagull集群需要保证大量实例一直处于可用状态。之前我们使用AWS的按需实例AWS ASGs,但对我们来说,要想达到这个容量成本太高了。


为了降低成本,我们开始使用一个叫FleetMiser的内部工具去维持Seagull集群。FleetMiser是一个用来测量基于不同信号的集群的自动缩放引擎,这些信号包括当前集群使用率、管道内的流量数等等。FleeMiser主要由以下两部分组成:


  • AWS Spot Fleet:AWS有现场实例,现场实例比按需实例成本低很多,Spot Fleet能提供交互界面更简单的现场实例。

  • 自动缩放:集群的使用时间不稳定,使用高峰主要集中在10:00-19:00(太平洋标准时间),此时,开发人员工作强度最大。为了动态调整范围,FleetMiser使用集群在不同优先级别下的当前和历史使用数据。Seagull集群每天的波动范围大概介于1500CPU内核和10000CPU内核之间。



FleeMiser为我们的集群节省了大约80%的成本。在使用FleetMiser之前,我们是使用AWS按需实例,没有自动缩放功能。



总结


Seagull使测试结果时长从2天缩短到了30分钟,同时也大大降低了执行成本。从今以后,开发人员可以安心敲代码,不用再花大量时间等待验证变化却束手无策。