目前JMeter在接口测试和性能测试的市场占用率是很高的,最大的原因是其开源性、易扩展和轻量级(这是Loadrunner不具备的),并且同时可以满足多种协议的接口和性能测试(这是其他开源工具不具备的)。而Metersphere是一款基于JMeter引擎技术的软件测试平台,不考虑轻量级因素,基本是可以替代JMeter,并且更易于线上测试工作的开展(在线管理用例、在线编辑脚本和调试脚本,在线压测和在线分析报告)。
JMeter虽然灵活轻巧,但其基于线下工具的特点,无法进行系统化和平台化的管理和运行,同时JMeter的单机模式在一般的压力机配置下,会受限于JMeter其本身的机制和硬件配置,最多可以支持几百至一千左右的模拟请求线程,而开展大量的分布式Slave部署,也会带来运维管理的困难,同时JMeter的主从(Master-Slave)模式,还会给主节点带来很大的交互压力,没人能做到部署大规模的分布式集群压测。
我们分析这个结构图会得出以下的结论:
(1)从主节点调度和传输数据,依赖于稳定的端口,其中server.rmi.localport和client.rmi.localport端口默认是随机的(也可以设置成如上图固定的),server_port端口一般固定为1099,只要防火墙没有放行(如果随机端口就要求关闭防火墙),Master-Slave主从分布式模式就会调度失败。
(2)主节点发送给从节点的数据相对少(因为除了主从调度和数据同步外,每个从节点作为独立的压力机,自行负责自己那部分请求发送和接收),但是从节点发送给主节点的测试结果数据一般会比较大,遇到大规模量从节点时,对主节点(主控机)的压力就会很大,容易出现瓶颈。
(3)每启动一个从节点(Agent),基本上Server_Port端口就被占用了,而且只能单任务压测,就算一个任务结束了,进程还在端口就不会释放,属于资源独占性。
(4)主从方案部署繁琐,除了考虑端口因素,还要考虑版本一致性,插件依赖包一致性,其中一个节点崩溃,可能就导致整个压测任务失败(因为要保证调度和主从数据一致性)。
(5)如果JMeter压测的CSV需要每个节点(Agent压测机)读取的数据不一样,则需要人为提前进行切分、裁剪和放置,因为主从控制没有文件远程传输和同步机制。
(6)如果从节点硬件性能差别大,也没法控制不同节点的压力分配来减轻某些节点的压力,因为节点机Agent只有发压功能,没有差异控制功能,线程设置多大,每个节点都复用一样的配置。
(7)另外,JMeter在GUI 模式下通过第三方插件可以查看实时压测报告(性能较差,一般不采用),No-GUI 模式下只能生成结果报告,目前一种常见的方式,就是通过后端监听器向InfluxDB发送结果数据,采用Grafana进行实时展示,但这种方式在大规模压测下InfluxDB也会崩溃,除非是InfluxDB集群(集群版的未开源)。
(8)JMeter默认是不支持性能监控的,只能是在GUI模式下,通过扩展监听器插件(如PerfMon Metrics Collector)来实现,但也只能监听到CPU、内存、网络这样的基础指标,可扩展性上有限。另外从性能上考虑,也非常不合理,本来Master节点压力就大,再加上监控数据的汇集,性能就更差了,所以除了采用独立部署的性能监控平台,没有别的办法。
我们分析以上架构图会得出结论:
(1)MeterSphere基于Docker技术,易于分布式集群的部署,如果配合Kubernetes就更易于扩展部署节点,也易于云部署。
(2)MeterSphere没有采用传统的JMeter Slave(Agent分压器)方式去扩展节点,而是每个节点都是独立的JMeter Master,好处就是不需要通过Server_Port端口来构建主从连接,每个节点就是个Docker版的JMeter进程,由NodeController控制,用完即停(通过Docker启动和注销)。
(3)测试结果和报告再也不用通过Slave向Master汇集,而是各自节点通过JMeter-Kafka监听类组件向Kafka回传测试结果数据,避免了主从模式下的Master汇集压力,而且Kafka还可以考虑集群化部署,这在性能上就可以满足大数据量的吞吐压力。
(4)MeterSphere将传给Kafka的结果数据采用DataStreaming进行收集和计算,并写入MySQL数据库,这又确保了在生成实时报告及汇总报告上的性能,我们都知道JMeter生成报告的性能一直比较差,特别是长时间压测写入了大量结果数据到文件中,想顺利转成html报告几乎不可能。
(5)MeterSphere基于界面化的设置性能压测参数(并发、时间、梯度、压测资源池、文件切分等),并通过资源池管理节点资源,根据资源池分发压测脚本和文件到指定的节点,自动启动Docker JMeter完成压测。
(6)测试用例(接口)、测试场景(脚本)全都入库保存和管理,测试数据和测试结果和报告也是入库保存和管理,方便后续分析、分享和比对。
(7)性能监控上支持扩展Prometheus,如配置了相关的Prometheus监控,MeterSphere在压测的同时会自动收集被压测端系统的性能监控数据。
JMeter虽然受到很多人推崇,但做为一款测试小工具,无法进行测试脚本管理、无法在线规化测试场景、无法多人实时查看测试过程和测试结果,总之不方便基于团队的方式开展接口测试和性能测试工作,更别提是基于项目的迭代实时做持续测试了。另外长期做过性能测试的都知道,接口测试和性能测试是有一定相关性的,比如性能测试的混合测试场景就是一些接口的组合,完全可以把测试通过的接口直接引用过来,就不需要重新定义和编辑了,同样,性能测试的场景规划也完全可以前移到接口测试阶段进行,而不至于到性能测试执行阶段了才开始准备测试脚本。这些事对于Web平台系统来说再平常不过了,但对于JMeter来说就不具备这样的管理方便性。
Metersphere可以说解决了我们上面所提到问题,即完全在线运行和管理,相当于将JMeter由线下搬到了线上,当然,这样一定会有人问,能在线编辑和调试测试脚本吗?毕竟很多基于Jmeter的开源测试平台,在线压测一般都没问题,但是要在线编辑脚本就有点困难,因为要在Web端做一套和Jmeter一样灵活的脚本编辑工具可没那么容易。对于这一点Metersphere做的挺不错,并且相信未来还会从Jmeter身上吸收更多的优点,我们先来看看Metersphere基于Web界面的接口定义和编辑开发能力:
(1)创建接口
目前支持创建接口包括Http、TCP、SQL、DUBBO,类型上还是偏少,比如还没支持websocket(接口配置没有该功能,但性能测试可以通过上传jmx脚本和websocket相关依赖jar包来实现)。对于接触过Jmeter或Postman的人来说,在上面创建接口操作起来相对容易,因为很多要素是一样的,更让人惊喜的是可以同步创建Mock服务,易用性上没的说了。
另外我们创建的接口除了能Mock化,还能文档化(相当于Swagger化),这点也挺棒:
(2)导入外部接口
支持导入多种格式的接口文件,目前http协议支持Postman、Swagger、JMeter,这也没谁了(你们说还有哪个接口测试平台支持这么多)。
以JMeter的脚本为例,导进来后,基本要素和JMeter一样,就是前置处理器、后置处理器、断言什么的都没了,不过没关系,可以进入Case或是在自动化接口场景模式上追加。如在后置处理操作中添加正则表达式提取Cookie参数:
可以执行调试,来看我们提取的效果:
可以看到这个正则表达式(如果响应体是JSON格式,除了正则,推荐用JSONPath提取,那样更方便精准,我这里提取的是响应头的Cookie,所以用正则)提取的是三个值的数组,我们只要取第二个值,作为我们的cookie参数,那么直接引用变量${cookie_2}就可以了,是不是和Jmeter上的操作类似。所以我就说会Jmeter的,接受这个Metersphere是很容易的(本来就是一套玩法)。把这个cookie引用到后面接口的请求头即可:
注明:其实导入外部接口的功能,还有另外一种现实意义,就是我们可以用其他工具,比如Postman、JMeter代理录制、Chrome录制插件等工具去录制接口脚本,然后导入Metersphere,这对于性能测试场景的构建提供了辅助手段,对于喜欢录制的小伙伴来说带来了很大帮助。
为什么很多人愿意使用Jmeter来做接口测试,除了它支持的协议多以外,最主要是容易进行场景化的编排,比如我登录后,获取token再传给查询接口,然后查询接口进行查询,查询到结果,传给操作接口进行修改或删除操作,这样的场景化就是业务特性,要求接口按先后顺序编排,彼此还要参数关联。而这样的场景化接口编排后,是可以很方便的直接引用到后期的性能测试场景的,所以接口场景化很重要,这一点Metersphere也做的不错(毕竟是基于Jmeter的技术)。
对于Jmeter技术理解比较深的话,了解和使用Metersphere是有帮助的,特别是接口自动化场景和性能测试场景,基本上属于技术同源:
X1~X5:是负载模拟的一个过程,使用这些组件来完成负载的模拟;
X1:选择协议,模拟用户请求,检查服务响应是否正确,并收集结果信息,属于Api定义部分;
X2:完善测试脚本部分,包括参数化,关联等,属于Case定义部分;
X3:控制测试脚本业务逻辑,属于业务场景定义部分;
X4:集合点,模拟用户并发,这属于性能测试涉及的内容;
X5:用户数,一个线程代表一个用户,调试接口一般单线程,性能测试就会用多线程;
Y1:可以理解为选择协议,包含负载模拟部分,负责模拟用户请求;
Y2:可以理解为检查点,结果验证部分,负责验证结果正确性,属于接口Case定义部分;
Z:可以理解为监控器,负责结果的收集,对于Jmeter来说监听器不仅可以放在线程组之内,也可以放在线程组之外;
对于Metersphere平台来说,无论接口测试,还是性能测试,都离不开以上要素结构,只是像监听器已经做到了高度集成,在平台里已融合到报告或监控中了,所以没有直观体现。
(1)创建场景
我们可以创建个场景,然后从上面定义好的接口,直接复制添加(从接口列表导入)过来:
除了导入过来的接口,我们也可以场景下直接添加新的接口,同样也可像Jmeter一样,添加事务控制器、循环控制器、条件控制器、自定义脚本(beanshell、Python等),如以下添加随机生成身份证号码的脚本:
可以说这个接口自动化场景编辑的功能,还是很强大的,对于我一个擅长Jmeter的测试人员来说,可以无缝接受。
(2)导入脚本场景
我试了下,把JMeter脚本导入,发现连线程组、事务和各Jmeter元件都一起导入了,如下:
很多元件目前是界面上不支持展现,但会以xml形式展现,可以编辑xml,比如Cookie管理器:
说到Cookie管理,可以用JMeter带的HTTP Cookie管理器(Metersphere界面目前没有提供这个元件,导入的显示为xml),也可以用我上面提到的正则表达式提取的方式,然后添加到其他接口请求头中(类似于token处理方式),当然,Metersphere也有自己的方式,就是Cookie共享,勾选了这个,其实就相当于是用了JMeter中的Cookie管理器的Cookie保存:
无论是新建场景,还是导入场景,其实Metersphere做的已经很出色了,基本上吸收了Jmeter的很多特性,并且从扩展上来说,还可以继续扩展Jmeter的一些元件,从开源的二次开发角度来说,我觉得难度应该不大。
(3)变量和参数化
关于参数化,主要有上面提到的关联提取方式,目前支持正则、JSONPath、XPath,基本上也够用了:
至于全局变量可以在项目环境配置中去配置,配置方式很灵活,可以直接添加变量,也可以在全局前置脚本中添加脚本产生变量:
从文件中导入变量,跟Jmeter中的CSV 数据文件设置类似,在场景编辑页面上方有场景变量链接,设置界面如下:
Metersphere相较于Jmeter的最大优势就是性能测试过程完全Web界面操作,包括脚本的上传和管理,参数化及资源文件的上传管理,压测在线配置,压测过程实时查看,压力机的性能监控,性能测试结果及报告管理,这些都是单机化的Jmeter所不具备的。
(1)测试资源
Metersphere比较好的地方,就是通过资源池来管理测试资源,而且一个资源池可以创建多个压测节点,这里的每个节点不是Jmeter传统理解的Slave(比如端口绑定1099的代理节点),而是关联一个新的Jmeter Master进程,这个进程就是通过Docker镜像在压测时动态创建容器,压测完后就自动消亡释放压测资源。以下是一个资源池创建两个节点的示例:
每个节点控制器NodeController负责创建和消亡Jmeter Master容器,NodeController也是个容器,所对应的默认端口为8082,docker ps | grep node-controller 结果如下:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3d8cbeab1861 registry.cn-qingdao.aliyuncs.com/metersphere/ms-node-controller:v1.19.0 "/deployments/run-ja…" 4 days ago Up 4 days (healthy) 0.0.0.0:8082->8082/tcp, 0.0.0.0:9100->9100/tcp ms-node-controller
(2)性能监控
Metersphere的节点部署模式(安装时install.conf配置MS_INSTALL_MODE=node-controller),启动后会看到三个相关容器,其中Jmeter Master容器是动态的(压测完就消亡),另外两个固定的,一个是上面提到NodeController,一个是node-exporter,很多人不知道node-exporter的作用,其实它是个性能监控采集器,相当于Prometheus监控平台中的node-exporter,有了它我们压测完后,在报告中是能看到采集到的压力节点性能监控数据:
上面的监控采集数据,基本上和Prometheus是一样的,可以肯定的是Metersphere对其做了一些集成,既然通过node-exporter能支持Linux性能指标的采集,那么我们除了监控压力节点机,我们还可以监控被测服务器,通过性能测试->测试->高级配置->监控,添加我们需要监控的服务器:
上面的方式可以按Prometheus的promQL语法自定义监控指标。那么毫无疑问,我们还可以按一般Prometheus的方式去扩展其他服务的监控,比如Mysql、Postgresql的监控等等,只需要在被监控机器上部署相应的采集器,比如Mysql Exporter、Postgres_Exporter、JMX Exporter等等,真正懂性能测试和性能监控的人应该都不难理解这方面的扩展需求,监控关系示意图如下:
(3)加载测试脚本
主要包括两种方式,一种是JMX文件(包括新上传的脚本或引用平台上已有的脚本),一种是引用上面提到的接口自动化场景(这也是平台化管理的优势):
本质上来说,上面提到的接口自动化过程,就是一个Jmeter脚本化的过程,最终压测调用的是JMX文件(会分发到各个节点),所以性能测试加载脚本和接口场景配置就是一个相通相关的过程。
(4)压力配置
基于界面的压力配置,比JMeter要简单直观,目前支持两种线程组发压模式,一种是ThreadGroup线性递增发压,一种是ConcurrencyThreadGroup是阶梯递增发压:
从配置上来说,支持选择资源池(每个资源池可能对应多个压测节点),支持多场景(同时或顺序执行多脚本),除了常规的并发配置项,还包括RPS(容量限制)配置:
压测可以自定义分配不同节点的压力配比(不同机器性能不一样,有时候要区别对待):
对于参数化文件,还支持CSVDataSet拆分(在高级配置中),可以按照分节点分隔压测数据,这是JMeter默认不具备的功能,但是在业务场景中经常需要的功能,配置页面如下:
对于我来说,目前Metersphere不支持动态调整TPS/RPS,这点挺不方便的,因为有时候长时间压测,需要继续加压时,我们是不希望中断测试的,希望能够动态加压。
(5)测试报告
Metersphere的测试报告算中规中举,但是相对于JMeter来说,优势明显,首先是可以实时直观的查看压测情况,最关注的TPS、RT指标、请求统计、错误记录都清晰明了。JMeter如果没有引入第三方插件的话,是不能直观的查看压力变化情况,当然JMeter测试结束后,导出的Html报告也很详细,这点来说,Metersphere有点不足,不过不影响我们的测试活动,毕竟最关注的指标也就这些,如果需要更多的报告视图,完全可以基于开源扩展开发。Metersphere的测试报告示例如下:
另外有个亮点,就是报告对比功能,我们可以把多轮测试的报告进行对比,比如比较TPS的提升情况,能清楚的说明性能的提升。
JMeter的最大优势是开源性,Metersphere的最大优势也是其开源性,Metersphere的另一个优势就是它是基于JMeter技术的。
JMeter最大的优势是支持多种协议的测试,这方面除了Loadrunner应该找不到第三款测试工具了吧(互联网大厂自己的工具不算,毕竟外人也不能免费享用),所以Metersphere的最大优势是基于JMeter去扩展各种协议接口的测试,比如WebSocket的测试。默认JMeter是不支持WebSocket的,但是可以扩展第三方的插件获得支持,对于Metersphere来说,我们也是同样的思路,我们可以把WebSocket第三方插件依赖Jar包全部上传,这样就能支持WebSocket协议脚本的压测:
上面的依赖包一次上传后,就可以直接在同一个项目中引用了,调测的效果如下:
所以Metersphere基本上可以做到支持JMeter所支持的所有协议和接口,就看你怎么去配置和使用,另外Metersphere也是基于Java的开源平台,我们可以通过二次开发去获得更多的扩展。
(1)监控方面可以扩展Prometheus,而Prometheus是开源的系统监控平台,相关的说明上面也有提到,具体的应用大家可以自己去Prometheus官网获得支持。Metersphere的系统设置中有相关的外接配置:
在UI测试方面,估计不久也会有相应的扩展,比如扩展Selenium的支持和应用。
(2)与目前流行的缺陷管理平台也做了相应的连接和集成,比如我们使用禅道比较多,就可以考虑这方面的集成应用,这就是开源扩展的优势:
对于我个人来说,目前Metersphere的最大不足,是不支持动态TPS/RPS/线程数的控制。实际工作中我们希望在每次压测执行时能够随时调节吞吐量或者动态改变压力的上限值。
以上两种情况,在一般的测试情况下影响不大,大不了重新开始执行测试,但是如果是在生产环境下测试,或者需要大量前置工作的情况下(准备大量测试数据或复杂的环境初始化工作),任何测试的中断,都意味着工作量的增大,所以压测过程中动态改变压力是很有必要的。
在JMeter中动态改变压力,是通过BeanShellClient和BeanShellServer来实现动态改变参数变量,如在节点jmeter.properties设置beanshell.server.port为9000,通过命令动态改变参数:
java -jar /lib/bshclient.jar localhost 9000 update.bsh <参数>
目前基于Metersphere进行这方面的改造有困难,一方面是开启beanshell.server.port就打破了原有JMeter-Master无需端口调用的优势(前面说到的优点),另外JMeter只支持DynamicThread动态线程技术的ConcurrencyThreadGroup、ArrivalsThreadGroup线程组和Constant Throughput Timer 吞吐量定时器等进行动态改变参数变量,适用性上有限。但是,还是希望Metersphere的工程师们能找到最佳的方案解决这个问题,哪怕是折中的方式通过外部手动配置也行。
关于JMeter动态压力的相关技术可以关注我的另一篇文章:Jmeter动态吞吐量实现_smooth-z的博客-CSDN博客_jmeter吞吐量在容量测试时,“控量”是非常重要的,JMeter 是根据线程数大小来控制压力强弱的,但我们制定的压测目标中的指标往往是吞吐量(QPS/TPS),这就给测试人员带来了不便之处,必须一边调整线程数,一边观察 QPS/TPS 达到什么量级了,为了解决这个问题,JMeter 提供了吞吐量控制器的插件,我们可以通过设定吞吐量上限来限制 QPS/TPS,达到控量的效果。https://blog.csdn.net/smooth00/article/details/121655220?spm=1001.2014.3001.5501
当然以上的想法不适合所有人,有很多人可能用不到这个功能,盲目做到产品化的Metersphere当中,可能会导致易用性和部署维护上变得糟糕,不过作为云压测系统重要的一个功能还是尽早考虑考虑。
写到这,发现自己写的很多了,就不再多说了。其实对于测试或技术工作来说,最重要的要素是人,其次才是工具,毕竟工具是死的,人是活的,再好的工具也得有懂它的人才能发挥价值,也只有人才能促进工具往好的方向演进。
Metersphere参见官网:MeterSphere - 开源持续测试平台 - 官网
开源代码:https://gitee.com/fit2cloud-feizhiyun/MeterSphere