使用JMeter进行性能测试 —“Java请求”方式
JMeter是Apache组织的开放源代码项目,它是功能和性能测试的工具,100%的用java实现,最新的版本是2.9,大家可以到官网下载源代码和查看相关文档。之前本科的时候,SQA课程作业中我们组使用过2.4版本,这次更新了2.9感觉最直观的就是界面上有了小的更改,增加了清除、启动等按钮。
关于使用JMeter进行JDBC数据库测试、HTTP请求接口测试、结合Badboy录制功能进行网站性能测试等内容,网上的资料比较丰富,这里就暂时不做介绍了。更实用和灵活的场景,是实用我们自己编写的jar包进行测试,这也就是“Java请求”方式的测试。这里主要记录一下我在学习这种测试方式时遇到的一些问题,和总体流程,算作一个记录和小总结。
1. JMeter安装
准确的来说,我认为JMeter是不需要安装的,下载好JMeter Binary版本后,在本地解压缩,进入bin文件夹,执行ApacheJMeter.jar文件即可。这里提供一个观望的2.9版本的下载链接,时间久了可能会失效,这个时候可以进入Apache JMeter项目主页再选择download页面。
打开JMeter程序后,我们可以看到JMeter的主界面,是下图的这个样子(2.9版本)。
2. 使用JMeter创建测试计划
如果我们希望实用JMeter进行性能测试,则首先需要创建一个测试计划,我们可以对测试计划进行保存,这样当我们下一次需要再次执行这个测试的时候,只需要打开已保存的测试计划文件(.jmx文件)就可以执行了,无需再次创建。
1)点击“测试计划”,在右侧输入框中可以修改测试计划的名称,并添加注释,这里我偷个懒就不改了,使用默认的。
2)为测试计划添加一组Threads,选择线程组。这组Threads就相当于是一组用户,每个显示代表一个用户执行相关操作。
3) 编辑线程组属性。设置响应内容,比较重要的是线程数、ramp-up period和循环次数。这里设置线程数为1、ramp-up period为1和循环次数1,即线程组中只有1个线程,这个线程在计划启动后1秒就开始执行,只执行1次。
图上的ramp-up period解释不正确,这个属性表示每个用户(线程)启动的迟延时间。例如,如果你输入Ramp-Up Period 为5秒,JMeter将会在五秒结束前完成启动所有的用户。所以,如果你有五个用户并且Ramp-Up Period为5秒,那么开始用户的延迟就是1秒。(5个用户/5秒=1用户每秒)。如果你设置的Ramp-Up Period为0,则JMeter将会立即启动你所有的用户。
如果勾选了“调度器”,则可以定时启动线程。
4)为线程组添加Sampler取样器,取样器表明这组线程执行测试的类型,即发送请求的类型、怎样发送请求的。我们这里选择“Java请求”,表明这组线程是通过某个Java类发送请求的。
4)编辑“Java请求”属性。下图这个大家可以发现已经有了Launcher类,和userName、password、authUrl的值了,这是因为:1. 我之前写了满足一定要求的代码,打了jar包,放入了JMeter的lib/ext文件夹下了,所以可以看到Launcher;2. 我在Launcher类中的getDefaultParameters方法中添加了默认的userName、password、authUrl值。这里的“满足一定要求”请继续参阅下文。
5)为Java请求添加监听器,选择“聚合报表”和“图形结果”,这样在启动测试后,我们就可以获得测试结果的数据,分别以报表和图形的结果展示。
6)点击启动(菜单栏中的绿色三角形按钮)。测试完成可以看到测试结果。为了结果好看一点,我把线程数改成了10,循环改成了100 :P
这里对测试结果中的几个指标进行说明:
样本数目 | 总共发送到服务器的请求数。 |
最新样本 | 代表时间的数字,是服务器响应最后一个请求的时间。 |
吞吐量 | 服务器每分钟处理的请求数。 |
平均值 | 是总运行时间除以发送到服务器的请求数,即每个请求的平均响应时间。 |
中间值 | 是代表时间的数字,有一半的服务器响应时间低于该值而另一半高于该值。 |
偏离 | 表示服务器响应时间变化、离散程度测量值的大小,即数据的分布。 |
90%line | 90%的响应时间都比这个时间小 |
Min | 代表时间的数字,是服务器响应的最短时间。 |
Max | 代表时间的数字,是服务器响应的最长时间。 |
Error% | 请求的错误百分比。 |
KB/sec | 是每秒钟请求的字节数。 |
3. 实现“Java请求”代码
针对"Java请求"类型的测试,需要基于JMeter测试框架编写测试用例。
1)新建一个普通的Java工程
2)添加JMeter的包引用,这些包位于 JMeter安装目录/lib/ext下,一般只需要ApacheJMeter_core.jar和ApacheJMeter_java.jar这两个。
3)新建一个Java Class,如下例中的“Launcher”,并继承“AbstractJavaSamplerClient”。AbstractJavaSamplerClient中默认实现了四个可以覆盖的方法,分别是“getDefaultParameters”,“setupTest”,“runTest”和“teardownTest”方法。
- getDefaultParameters 方法主要用于设置传入界面的参数;
- setupTest方法为初始化方法,用于初始化性能测试时的每个线程;
- runTest方法为性能测试时的线程运行体;
- teardownTest方法为测试结束方法,用于结束性能测试中的每个线程。
package cn.edu.zju.swift.test; import org.apache.jmeter.config.Arguments; import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient; import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext; import org.apache.jmeter.samplers.SampleResult; import cn.edu.zju.swift.JtangSwiftClient; import cn.edu.zju.swift.model.result.AccountResult; public class Launcher extends AbstractJavaSamplerClient{ private JtangSwiftClient client; @Override /** * JMeter界面中展示出此方法所设置的默认参数。 * @return */ public Arguments getDefaultParameters() { Arguments args = new Arguments(); args.addArgument("authUrl", "http://192.168.3.51:8080/auth/v1.0"); args.addArgument("userName", "test:tester"); args.addArgument("password", "testing"); return args; } /** * 执行runTest()方法前会调用此方法,可放一些初始化代码 */ @Override public void setupTest(JavaSamplerContext context) { // 创建SwiftClient this.client = new JtangSwiftClient(15000, 15000, 8192, true, false); } /** * 执行runTest()方法后会调用此方法,可放一些资源释放代码 */ @Override public void teardownTest(JavaSamplerContext context) { // 关闭连接 this.client.close(); } @Override /** * 性能测试时的线程运行体,执行的业务方法放在这里。 */ public SampleResult runTest(JavaSamplerContext context) { // 创建SampleResult对象,用于记录执行结果的状态,并返回 SampleResult sampleResult = new SampleResult(); // 获取JMeter中输入的用户参数 String authUrl = context.getParameter("authUrl"); String userName = context.getParameter("userName"); String password = context.getParameter("password"); // 开始 sampleResult.sampleStart(); AccountResult accountResult = client.auth(authUrl, userName, password); // 暂停 // sampleResult.samplePause(); // 重启 // sampleResult.sampleResume(); // 结束 sampleResult.sampleEnd(); sampleResult.setSuccessful(accountResult.isSuccess()); // 返回 return sampleResult; } }
4)代码编写完毕后,把上面的例子打包(使用eclipse右键项目 -> export -> jar,即可)。然后把生成的"swift-random-action-test.jar"文件拷贝到JMeter的安装目录lib\ext下,就可以在上述“2. 使用JMeter创建测试计划”的4)Java请求编辑页面的下拉列表中看到Launcher类了。
这里有两点需要注意:
1. 如果你的jar依赖了其他第三方jar,需要将其一起放到lib/ext下,否则会出现ClassNotFound错误,这个问题也是困扰了我好久的 T^T;
2. 如果在将jar放入lib/ext后,你还是无法找到你编写的类,且此时你是开着JMeter的,则需要重启一下JMeter。
以上就是使用JMeter的Java请求方式进行一个测试计划构建的全过程了,都是比较基础的方法,如果需要什么额外的功能还可以慢慢学习。虽然自己也有写多线程并发的客户端测试代码,并自己收集response time等,计算TPS,但显然使用JMeter的方式更加方便,因为你只需要按照单线程的方式去实现你的测试业务,也无需添加各种埋点收集数据。
综上,感觉JMeter还是很强大的,最近打算多学习一点,对以后写代码,自我测试性能也是很有帮助的,再配合jProfiler的使用,可以很好的保证Java代码的效率和性能。当然,工具只能“锦上添花”,最根本的还是需要我们自己可以编写出高质量的代码啦 :D