有赞全链路压测引擎的设计与实现Word格式文档下载.docx
《有赞全链路压测引擎的设计与实现Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《有赞全链路压测引擎的设计与实现Word格式文档下载.docx(9页珍藏版)》请在冰豆网上搜索。
以用户下单这个场景为例,用户完成一笔订单,可能需要打开商品主页-加入购物车-选择收货地址-下单支付这些步骤,而串起这一系列的请求就是所谓的将请求编排成业务场景
∙流量控制
流量控制可以是纵向的,如上述下单场景中,各个步骤的请求量逐渐减少,整体呈现一个漏斗模型;
也可以是横向的,比如用户正在浏览A商品的商品详情页,然后看到了B商品的推荐,转而浏览B商品的商品详情页
∙压力控制
指压测时并发用户数、吞吐量(RPS/TPS)的控制
∙数据跟请求参数的绑定
压测往往涉及大量的测试数据,而如何绑定数据和请求参数是我们需要考量的
∙对分布式测试的支持
因为是全链路压测,自然需要多台施压机共同协作施压,自然而然的需要分布式支持
∙测试报告
良好的测试报告是我们分析性能问题的必备条件
∙二次开发的成本
由于时间或人力关系,我们也需要考虑二次开发成本
1.2、4个主流开源性能测试框架对比
我们调研了以下4个主流开源性能测试框架:
∙ApacheBench
Apache服务器自带,简单易用,但不支持场景编排、不支持分布式,二次开发难度较大
∙JMeter
JMeter支持上述很多特性,如分布式、良好的压测报告等,但其基于GUI的使用方式,使得当我们的压测场景非常复杂并包含很多请求时,使用上不够灵活;
此外在流量控制方面的支持也一般
∙nGrinder
基于Grinder二次开发的开源项目,支持分布式,测试报告良好,但和JMeter一样,在场景编排和流量控制方面支持一般
∙Gatling
支持场景编排、流量控制、压力控制,测试报告良好,且提供了强大的DSL(领域特定语言)方便编写压测脚本,但不支持分布式,且使用Scala开发,有一定开发成本
以上,我们最终选择基于Gatling做二次开发。
2、Maxim新增的特性
Maxim在Gatling基础上开发了很多新特性:
∙支持分布式
一个控制中心(ControlCenter,负责调度)+多个压力注入器(指施压机)
∙提供GUI,并对用户隐藏压测过程的复杂性
高效地创建、运行(手动/定期)测试任务
∙管理测试资源
测试资源包括压测脚本、数据集(为压测请求提供测试数据,由数据块构成的一个集合,数据块是大量测试数据的最小分割单元)、压力注入器
∙支持压测脚本参数化
Maxim中并发用户数、RPS、持续时间等都可以通过GUI动态注入压测脚本
∙支持压力注入器系统状态监控
实时监控压力注入器的CPU、内存、I/O等指标
∙自动生成压测报告,保留历史压测报告
采集多个压力注入器的压测日志,自动汇总生成压测报告,并保留历史压测报告
3、Maxim的技术架构
3.1、Maxim的总体架构
Maxim架构的主要构成:
∙MaximConsole
MaximConsole主要衔接GUI和MaximControlCenter,负责创建、运行测试任务,接收压力控制参数等
∙MaximControlCenter
Maxim的控制中心,这里主要负责压测任务的调度、读取数据集、上传脚本和数据以及读取日志并生成压测报告
∙LoadInjectorCluster
压力注入器集群,主要分为Agent和Gatling两部分,Agent负责接收Maxim控制中心的调度指令以及向控制中心反馈本压力注入器压测情况,而Gatling则是真正发起压测请求的地方,并将压测日志写入InfluxDB
∙DataFactory
压测数据首先会在大数据平台通过MapReduce任务生成,而数据工厂负责为控制中心读取这些数据并返回数据集
∙CloudStorage
云存储,Maxim控制中心会将压测脚本和压测数据上传到云存储,当Agent收到控制中心的任务执行指令时,会从云存储下载压测脚本和对应的数据块。
设计云存储的目的主要是为了模拟真实用户环境在公网发起压测请求,但有赞目前都是从内网发起压测请求,所以云存储的功能也可以以其他方式实现,比如Agent直接从大数据平台下载数据集
∙InfluxDB
所有压力注入器产生的日志都会统一写入InfluxDB,方便生成压测报告
Maxim的调度算法
控制中心会根据当前测试任务使用的压力注入器数量,将数据集中的数据块平均分配给每个压力注入器,让每个压力注入器只下载对应的那些数据块。
此外,并发用户数、RPS也会被平均切分给每个压力注入器。
这样,每个压力注入器的负载基本是一致的。
3.2、Maxim的领域抽象
∙TestJob-JobExecution-JobSliceExecution
当压测任务开始执行,首先会在控制中心生成JobExecution,监控本次压测任务的整体执行状态。
控制中心又会根据上述调度算法为每个压力注入器生成任务分片JobSliceExecution并下发到各个压力注入器,其中包含了脚本、数据集等信息
∙TestScript
压测脚本
∙DataSet和DataChunk
数据集和组成数据集的数据块单元,目前单次压测任务已支持多数据集,为多个场景提供不同的压测数据,即混合场景压测
∙LoadProfile
从GUI接收动态参数,主要包括压力注入器数量、并发用户数、RPS、持续时间等
∙ExecPlan
执行计划,包括按需执行和周期执行两种执行方式
∙ExecutionStatus
关于状态机下一节会详细介绍
3.3、Maxim的状态机
Maxim状态机是Maxim分布式的核心,控制中心和各个Agent的行为都受状态机变化的影响。
创建任务并开始执行以后,各个任务分片(JobSliceExecution)首先会进入preparing状态,各个Agent会从云存储下载压测脚本和各自对应的那些数据块,下载完成后再将这些数据块合并成一个Json数据文件作为压测脚本的数据输入。
如果下载失败则会重试,即Prepare。
如果所有Agent都成功下载了脚本和数据,则各个JobSliceExecution会相继进入prepared状态,等所有JobSliceExecution进入prepared状态后,JobExecution也会进入prepared状态,并向各个Agent发起执行指令,各个JobSliceExecution进入running状态,等所有Agent执行完成且各个JobSliceExecution变成completed状态之后,JobExecution也会进入completed状态,此时压测任务执行完成并生成压测报告。
如果各个任务分片在preparing、prepared或running过程中有任何一个出错,则出错的分片会进入failed状态并通知控制中心,控制中心则控制其他分片中止正在执行的任务并进入Stopping状态,等这些分片中止成功并都变成stopped状态后,JobExecution会被置成failed状态。
当然了,也可以手动停止压测任务,这时候JobSliceExecution和JobExecution都会被置成stopping->
stopped状态。
3.4、Maxim控制中心的技术架构
Maxim控制中心采用六边形架构(也叫端口与适配器模式),核心服务只处理核心业务逻辑(如调度算法),其他功能如与Agent通信、脚本存储、数据存储、压测报告等都是通过适配层调用特定实现的API实现。
具体技术的话,与Agent通信使用grpc实现,其他功能则是通过SPI技术实现,我们把这一层叫做接缝层(Seam)。
这样设计最大层度的解耦了核心业务逻辑和其他功能的特定实现,我们在保持接缝层API不变的情况下,可以自由选择技术方案实现相应的功能。
比如数据服务这块强依赖了有赞的大数据平台,假设我们开源了Maxim,外部团队就可以选择他们自己的技术方案实现数据服务,或者为了测试目的Mock掉。
4、改造Gatling
原生Gatling是将压测日志写入本地日志文件的,而在分布式中,如果每个压力注入器都把日志写在本地,则为了基于所有日志分析生成压测报告,我们需要首先收集分散在各个压力注入器中的日志文件,这样显然是低效的。
所以我们改造了Gatling,将所有日志都写到同一个InfluxDB数据库。
需要生成压测报告时,控制中心从InfluxDB数据库读入本次压测任务的所有压测日志并保存为一个日志文件,再交由Gatling的日志处理模块来生成压测报告。
5、扩展Gatling
原生Gatling不支持Dubbo压测,所以我们扩展Gatling,实现并开源了gatling-dubbo压测插件,具体实现方法详见Dubbo压测插件的实现——基于Gatling
6、Maxim的未来展望
Maxim目前还是个单打独斗的产品,未来我们希望与大数据平台、运维平台等系统打通,让Maxim逐渐进化为一个一站式的压测平台,并引入更多新特性,如压测过程和压测报告的实时计算和展示等等。
我的系列博客
混沌工程-软件系统高可用、弹性化的必由之路
异步系统的两种测试方法
Dubbo压测插件的实现——基于Gatling
我的其他测试相关开源项目
捉虫记:
方便产品、开发、测试三方协同自测的管理工具
gatling-dubbo:
扩展自Gatling的Dubbo性能测试插件
招聘
有赞测试组在持续招人中,大量岗位空缺,只要你来,就能帮你点亮全栈开发技能树,有意向换工作的同学可以发简历到sunjun【@】
-全文完-