jmeter做简单的压力测试
背景
前阵子我们负责接入大众点评的CAT来做链路监控,接入的时候发现有可能会影响服务性能,于是乎,我用jmeter对接入CAT的web项目和dubbo服务做了分布式压力测试。之前没有做过压力测试,这次基本是把jmeter的基础功能都大致走了一遍,踩遍了一次坑。
基本原理
jmeter通过创建多个线程尽来模拟并发数,而做分布式压测,是考虑到单台jmeter压测服务器的性能有限,所以采用多台机器一起模拟高的并发数。分布式压测的时候,会设置其中一台为master,测试脚本会上传到master机器上,不需要上传到slave的压测机器,执行脚本的时候jmeter master会将jmx脚本传到slave机器,执行后将结果回传到master机器。
测试前机器准备
采用linux服务器模拟生产环境进行压测,不要使用UI界面进行压测,官方文档说清了,UI界面执行的效果不佳,推荐使用脚本方式进行执行。
jmeter版本: 统一使用3.2最新版本
linux服务器配置:
2台jmeter 客户端,2核 8G,
1台dubbo服务部署服务器, 2核 8G
jmeter相关测试结果分析插件:
这些插件是用来分析和展示每次压测的结果,都是在PC端使用,linux服务器并不需要安装。
- plugin manager, 用于管理所有的jmeter插件
- Response Times Over Time, 用于展示响应时间的图表插件
- Transactions per Second , 用于展示TPS的图表插件
安装方式,插件下载之后,解压之后,内容分 XX.jar 和 文件夹ext,这里的XX.jar拷贝到jmeter安装目录lib目录,ext下的文件拷贝到 jmeter安装目录lib/extra目录,然后重启即可。
测试标准基线
在制定测试的性能基线时,请教了公司的QA,但是没有谁能给我一个很标准的参考,于是在请教了其他几个同事之后,大概定了以下的最低性能基线:
- 接入CAT之后的TPS最多比没接入CAT的低10%
- 接入CAT之后的请求响应时间最多比没接入CAT的高10%
测试思路
- 部署测试的dubbo服务(没有接入CAT)在 部署机器
- 同时启动2个jmeter客户端,每个客户端各自开启2个线程,然后每隔30秒每个客户端再增加2个线程,直到最后每个客户端开启到20个线程,最后再持续运行1分钟后,每1秒钟关闭5个线程。
- 提前做好3台服务器的zabbix监控,监控CPU内存信息
- 部署测试的dubbo服务(有接入CAT)在 部署机器,重复2步骤
- 收集2次测试结果下载到本地进行图表展示和分析
详细实施过程
1.准备jmeter测试脚本
jmeter支持多种请求,包括http请求、java请求、SOAP等,这次我们做的dubbo服务压测,所以是属于java请求。
准备测试脚本是在jmeter UI进行创建测试计划,然后在将测试计划输出为jmx文件,即测试脚本。
测试dubbo服务,主要分成2步:
第一步:创建测试主类的jar包
根据jmeter的文档,需要将测试内容打包成一个jar包放入jmeter安装目录 lib/ext下,然后测试主类需要继承AbstractJavaSamplerClient类,该类的主要方法如下:
public Arguments getDefaultParameters();设置可用参数及的默认值;
public void setupTest(JavaSamplerContext arg0):每个线程测试前执行一次,做一些初始化工作;
public SampleResult runTest(JavaSamplerContext arg0):开始测试,从arg0参数可以获得参数值,调用逻辑在此;
public void teardownTest(JavaSamplerContext arg0):测试结束时调用;
使用示例:
public class TestRisk extends AbstractJavaSamplerClient {
private BlackRecordProvider blackRecordProvider;
@Override
public void setupTest(JavaSamplerContext context) {
DubboInit init = DubboInit.getInstance();
init.initApplicationContext();
blackRecordProvider = (BlackRecordProvider)init.getBean("blackRecordProvider");
}
@Override
public void teardownTest(JavaSamplerContext context) {
super.teardownTest(context);
}
// 测试调用过程
public SampleResult runTest(JavaSamplerContext javaSamplerContext) {
SampleResult result = new SampleResult();
result.sampleStart();
BlackRecordRequest request = new BlackRecordRequest();
request.setPage(1);
request.setPageSize(10);
try {
BlackRecordResponse response = blackRecordProvider.queryBlackRecord(request);
result.setSuccessful(true);
result.setDataType(SampleResult.TEXT);
result.setSamplerData(response.getMessage() + " " + response.getCode() +
" ");
} catch (Exception e) {
result.setSuccessful(false);
result.setResponseMessage("exception:" + e.getMessage());
} finally {
result.sampleEnd();
}
return result;
}
}
第二步,创建测试计划
在准备好jar包之后,需要创建测试计划,测试计划主要包含线程组、Sample(请求类型),监听器(运行结果的分析展示)。举例说明:
- 创建线程组
“Stepping Thread Group” 是指在压测过程线程数会逐步上升 的线程组类型,并且制定每次增加之后运行多长时间,最后逐步关闭所有线程。
有个注意的地方是,这里的线程总数不可以太高,如果太大,比如开始就启动200个线程,那么服务器可能一下子就CPU 100%,看不到最佳的效果,没有接入和接入CAT的区别不明显。所以在这里采用一开始每台机器启动2个线程,然后每隔30秒添加2个线程进行压测,最终在每台测试机器的测试线程达到20线程的时候,逐步终止压测。这里的20,是根据脚本压测过程观察服务器在最大开启多少线程的时候,服务器会有性能瓶颈,也就是每核达到70%的使用率。 - 创建java请求
- 添加分析解析结果的视图,包括TPS + 响应时间
添加响应时间
TPS
- 保存测试计划
点击保存,将测试计划存为jmx文件,也就是最终的测试脚本,并上传到jmeter压测客户端的服务器。2.jmeter客户端配置
这一步主要是配置jmeter客户端压测的基本参数,主要是jmeter客户端的地址配置:
修改bin/jmeter.properties修改remote_hosts为 2台jmeter客户端的ip:port,类似:
remote_hosts=10.10.223.11:1888,10.10.223.12:18883.执行jmx脚本
jmeter -n -t -r XXX.jmx -l XXX.jtl
将结果输出到jtl文件,然后下载jtl文件进行分析。
注意点:
1.测试过程需要及时看日志,确认是否连接上,日志文件在 bin/jmeter.log,确保压测的时候有连接上
2.观察jmeter服务器负载,确认是否因客户端负载过高影响压测效果
4.分析和统计测试结果
TPS
获得jtl文件之后,下载到本地,在jmeter客户端打开,分别2次打开压测结果的jtl文件,看看最终结果进行比较,如下:
Response Times Over Time
由于采用的是线程逐步递增的方式,可以在结果上看到响应时间是逐步的增高:
2次压测比较结果
导出csv进行统计
将统计结果导出成csv文件,然后统计计算最终的结果
然后根据时间段,比较下2种压测结果。
根据统计结果,接入CAT的dubbo服务会在造成10%左右的性能下降,属于可以接受范围