1 概述
1.1 导读
在进行项目基准性能测试过程中,我们发现单个进程压测最大tps在200左右,即使线程增加到400个,最大tps还是维持在200左右,响应时间持续上升,并且服务器硬件资源未得到充分利用,
具体对比数据见下文2.3.5。为了更全面地评估项目系统的性能,因此考虑采用Jmeter分布式压测方案,以获取更准确的基准性能数据。接下来,本篇文章将详细探讨Jmeter分布式压测在项目性能测试中的具体应用。
1.2 性能测试的实现目标
模拟大量高并发请求,对当前项目产品做一个性能摸底测试,获取系统的基准性能数据;
2 具体实践
2.1 组件介绍
主要使用两种开源组件,一种是JMeter,功能强大的压测组件,另一种是Ansible,方便批量管理JMeter子节点,
2.1.1 Jmeter
JMeter(Apache JMeter)是一个用于性能测试的开源工具,最初是为测试Web应用程序而设计的,但现在已经扩展到测试各种协议和服务器,本次压测主要使用beanshell 调用java jar(项目常见使用方式就是引用java jar 进行文件上传、下载)进行压测。
2.1.2 Ansible
Ansible 是一种自动化工具,用于配置管理、应用程序部署、任务自动化等。它通过简单的描述文件(通常是 YAML 格式)来描述所需的系统状态或操作,并在远程系统上执行这些操作,压测过程中,有些操作需要借助Ansible批量进行,如关闭、查询所有slave节点的所有jmeter进程。
2.2 具体安装配置过程
2.2.1 压力机信息
ip | 角色 | Jmeter进程数 | Ansible 主机名 |
S1 | slave | 20 | ansible-web1 |
S2 | slave | 20 | ansible-web2 |
S3 | slave | 20 | ansible-web3 |
S4 | slave | 20 | ansible-web4 |
S5 | slave | 20 | ansible-web5 |
M1 | master | 20s+1m | ansible-master |
所有配置都是CPU:48; RAM: 251GB; Bwidth: 20Gb
通过命令 ssh-copy-id -i {{ ip }} ,master 和slave 节点已经实现免密登录。
注意:
1、实际压测过程中,尽量将master节点和slave节点分开,本次压测因为机器数量有限,未做分离,所以M1机器有一个master进程,20个slave进程。
2、ip地址脱敏后,以S1..5代替。
2.2.2 Jmeter分布式安装配置过程
官网下载地址:
https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-5.5.zip
本次压测主要有5个slave节点,每个节点20个进程,其中一个slave节点的jmeter进程目录如下:
每个进程目录,以端口号作为后缀去区分。
1.在 JMeter master节点和slave节点,都安装 Java(jdk1.8)配置好JMeter(配置环境变量),并确保版本相同。
2.在JMeter master节点,修改 jmeter.properties 文件中server.rmi.ssl.disable的值从false改为true,并去掉注释。修改完成将该文件复制到所有slave节点上,所有jmeter进程对应目录中;可使用scp命令。
注意:示例jmeter安装目录是/root/jmeter/
为什么要修改这个配置?
因为Master 节点和slave节点主要使用rmi协议通信,如果你在使用RMI(远程方法调用)进行远程通信时,可能会遇到SSL相关的设置。将server.rmi.ssl.disable设置为true通常是为了禁用RMI的SSL(Secure Socket Layer)功能,主要原因如下:
简化配置:有时候,在开发或测试环境中,你可能不需要启用SSL加密通信,因为你的通信可能仅在受信任的网络环境中进行。禁用SSL可以简化配置和部署流程。
避免性能开销:启用SSL会增加一些额外的性能开销,包括加密和解密数据。在某些情况下,如果你的应用程序对性能要求较高,可以禁用SSL以避免这些开销。
调试和故障排除:在调试或故障排除过程中,禁用SSL可能有助于排除与SSL相关的问题。通过禁用SSL,你可以确定问题是否与SSL配置有关。
-
3.在一台slave机器上起多个jmeter进程,用端口号去区分,因此得修改每个jmeter进程目录中/root/jmeter/apache-jmeter-5.5-{{port}}/bin/jmeter-server文件里的端口号和文件名保持一致,并且RMI_HOST_DEF=-Djava.rmi.server.hostname=要和本机ip保持一致,
如截图/root/jmeter/apache-jmeter-5.5-1599目录中,jmeter-server文件里的端口号改成了1599,
其他进程如:
apache-jmeter-5.5-1299 … apache-jmeter-5.5-2999等等,要和上述配置保持一致。
注意:这只是其中一个slave机器,其他4台slave机器也需要重复的配置流程,修改配置文件。
2.2.3 Ansible安装配置过程
注意:ansible 版本是2.9.27
1. yum 安装 ansible,“yum -y install ansible”
2. 配置hosts域名清单,如截图:
3. 配置主机清单文件,如截图
4. 测试ansible是否可用
在master 节点 执行 ansible webservers -m ping -o
出现上述现象,说明ansible 安装成功,可投入使用。
2.3 具体压测实践
2.3.1 Gui 模式下编写好测试计划,
如截图:
添加所需的阶梯压测插件、统计插件等,保存至文件root.jmx。
2.3.2 将root.jmx 文件上传至固定目录中
上传至/root/jmeter/apache-jmeter-5.5-master/bin/目录中,
2.3.3 编写开启、关闭slave 节点的shell 脚本
开启slave节点shell 脚本:
关闭slave 节点shell脚本:
以上两个脚本需要每个节点,所有jmeter进程的/root/jmeter/ 目录下都要存在,方便ansible对子节点jmeter进程进行管理。
2.3.4 Jmeter分布式压测
-
1. 开启所有slave 节点之前,使用下述命令,先查看所有子节点有多少jmeter 进程
-
ansible webservers -m shell -a 'ps -ef|grep './ApacheJMeter.jar' | grep -v grep |wc -l' -v
如果第一次执行或者经过一轮压测后jmeter进程全被关闭,则会出现下述截图:
如果出现如下截图
ansible-web1 | CHANGED | rc=0 >> 20 说明还是有jmeter进程运行,如果运行开启全部jmeter进程命令,会提示端口被占用。
需要执行kill 命令,关闭所有节点所有jmeter进程,如下:
ansible webservers -m shell -a 'cd /root/jmeter/ && sh killalljmeter.sh'
可多次运行关闭所有jmeter进程命令。
-
2.执行开启slaver jmeter 进程命令
ansible webservers -m shell -a 'cd /root/jmeter/ && sh startslaver.sh'
怎么知道所有进程启动成功了呢?
再次执行命令
ansible webservers -m shell -a ' ps -ef| grep './ApacheJMeter.jar' | grep -v grep |wc -l' -v
查看每个salver 节点的进程是否全部启动成功
因为我每个slaver 节点启动了20个jmeter进程,所以命令返回数字是20个。截图返回的意思是ansible-web1、ansible-web2 、ansible-web3 、ansible-web4、 ansible-web5五个节点,每个节点20个jmeter进程全部成功运行。
-
3.最后就是最关键的一步了,那就是开启压测,
执行命令解析:
cd /root/jmeter/apache-jmeter-5.5-master/bin/ && ./jmeter -n -t root.jmx -j jmeter.log -R ip:port....
如果有多个jmeter进程,只需追加ip和端口号,逗号隔开即可。
这个命令的作用是在后台启动 JMeter 进程,并使用指定的测试计划文件执行性能测试,同时将执行日志输出到指定的日志文件中,其中cd /root/jmeter/apache-jmeter-5.5-master/bin/,进入到 JMeter 的 bin 目录中,这是JMeter 可执行文件所在的目录。
nohup ./jmeter:nohup 命令用于在后台运行程序,并忽略挂断信号。./jmeter 是执行 JMeter 可执行文件的命令。
-n:这个选项告诉 JMeter 以非 GUI 模式(Non-GUI mode)运行,即在无图形用户界面的情况下执行测试计划。
-t 单个文件.jmx:-t 选项后跟着要执行的JMeter 测试计划文件名。在这里,单个文件.jmx 是要执行的测试计划文件的文件名。
-j jmeter.log:-j 选项后跟着要写入的日志文件名。在这里,jmeter.log 是执行过程中产生的日志信息将要写入的文件名。
-R ip:port,ip:port,...:-R 选项用于指定远程服务器节点,其中包括要执行测试的远程服务器的 IP 地址和端口号。在这里,列出了一系列的远程服务器 IP 地址和端口号。
执行如下命令,开启2个slave节点,总共20个jmeter进程,阶梯加压至200个线程,运行20分钟后结束
cd /root/jmeter/apache-jmeter-5.5-master/bin/ && ./jmeter -n -t 单个文件.jmx -j jmeter.log –R ip1:1099 … ip2:2999。
由服务器监控软件可知
三个存储服务器节点ioutil 平均达到95%,说明服务器io很繁忙,
在其中一台存储服务器节点,执行 iostat -x -d -m 1 命令,打印每个磁盘繁忙程度,由下截图可知
几个主要磁盘,ioutil 平均达到90%左右.
执行top,点击1,超过一半的cpu的wa 值较高,平均达到30%左右,有些甚至超过70%,说明 io等待时间较长。
此时说明这个集群io性能已达到瓶颈了
Jmeter 性能数据监控如下:
采用阶梯加压的策略,当线程数加到80个左右 ,即使再增加运行线程数,tps稳定在tps达到2200左右,有23个报错(错误率极低)。
由提供的综合数据来看。接下来有两种选择,第一可以增加jmeter进程,继续加压,查看系统崩溃前的性能数据,第二可以降低jmeter进程,查看在系统稳定请求的情况下的各项数据,无论哪种选择,都可以使用上述开启命令,无非就是增加或减少几个jmeter进程而已。
2.3.5 单个jmeter进程和分布式压测结果对比
使用相同的root.jmx脚本,相同的测试系统,在相同的压测场景下,对比查看系统性能数据表现。
1、单进程200线程数
执行如下命令,运行20分钟后结束
cd /root/jmeter/apache-jmeter-5.5-master/bin/ && ./jmeter -n -t 单个文件.jmx -j jmeter.log
由服务器监控软件可知,
三个存储服务器节点ioutil 平均达到13%,说明服务器io不是很繁忙,cpu和内存利用率较低,还有很大提升空间。
Jmeter 性能数据监控如下:
Tps一开始就是200tps左右,随着线程不断增加,tps一直维持在200左右,其中95%的response time 随着线程阶梯增加而增加。
2、单进程400线程数
执行如下命令,运行20分钟后结束
cd /root/jmeter/apache-jmeter-5.5-master/bin/ && ./jmeter -n -t 单个文件.jmx -j jmeter.log
由服务器监控软件可知,
三个存储服务器节点ioutil 平均达到13%,说明服务器io不是很繁忙,未达到io极限。cpu、内存利用率较低,还有很大提升空间。
Jmeter 性能数据监控如下:
Tps一开始就上升至200tps左右,随着线程阶梯增加到400个线程时,tps持续回落,稳定在183左右,其中95%的response time随着线程阶梯增加而增加,达到2.46s左右
整理以上数据可得下表:
进程数(个) | 最大线程数(个) | Tps(t/s) | 响应时间(ms) | Ioutil(%) |
1 | 200 | 200 | 1000 | 13 |
400 | 183 | 2460 | 13 | |
20 | 200 | 2200 | 130 | 93 |
总结:在进行大并
2.4 踩坑记录
2.4.1 Engine is busy - please try later
如截图:
原因是是因为,子节点的jmeter进程压测任务尚未完成,如果此时再次执行压测命令,就会提示“Engine is busy - please try later”,解决方案也很简单,先执行关闭全部jmeter进程,然后执行开启全部进程命令,最后执行压测任务命令,具体操作见2.3.4;
2.4.2 部分jmeter进程启动失败
类似如下截图:
执行查询jmeter命令,发现“ansible-web3” 节点只启动了19个进程,有一个启动失败,
解决方案,先查询hosts域名清单,见2.2.3,ansible-web3对应的机器ip上,执行
ps -ef| grep './ApacheJMeter.jar' | grep -v grep,
如截图:
可以看到具体哪个进程没有启动,找到以后,执行命令运行,
cd /root/jmeter/apache-jmeter-5.5-{{$port}}/bin/ && nohup ./jmeter-server &
另一种解决方案,就是再次执行关闭全部进程命令,然后执行开启所有进程的命令。
3 未来展望
该分布式压测相关组件,已沉淀成一套“开箱即用”的脚手架,想要使用的小伙伴只需下载压缩包,本地服务器解压并进行相关配置既可使用,未来会打成Docker镜像,更加方便各位使用。
4 总结
本文详细介绍了分布式压测方法在项目性能测试中的落地过程,通过利用多台机器进行Jmeter分布式压测,实现了模拟更大规模的用户并发访问系统,从而更好地评估系统在高负载情况下的基准性能数据。希望能为想要进行高并发性能测试的小伙伴提供参考。
最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:【文末自行领取】
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!