感悟时分 发表于 2018-4-12 15:49:56

使用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用户每秒)。如果你设置的Ra
mp-Up Period为0,则JMeter将会立即启动你所有的用户。

如果勾选了“调度器”,则可以定时启动线程。


4)为线程组添加Sampler取样器,取样器表明这组线程执行测试的类型,即发送请求的类型、怎样发送
请求的。我们这里选择“Java请求”,表明这组线程是通过某个Java类发送请求的。



4)编辑“Java请求”属性。下图这个大家可以发现已经有了Launcher类,和userName、password、authU
rl的值了,这是因为: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和Ap
acheJMeter_java.jar这两个。

3)新建一个Java Class,如下例中的“Launcher”,并继承“AbstractJavaSamplerClient”。AbstractJavaSam
plerClient中默认实现了四个可以覆盖的方法,分别是“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 tim
e等,计算TPS,但显然使用JMeter的方式更加方便,因为你只需要按照单线程的方式去实现你的测试业务,
也无需添加各种埋点收集数据。

综上,感觉JMeter还是很强大的,最近打算多学习一点,对以后写代码,自我测试性能也是很有帮助的,
再配合jProfiler的使用,可以很好的保证Java代码的效率和性能。当然,工具只能“锦上添花”,最根本的还
是需要我们自己可以编写出高质量的代码啦 :D

qqq911 发表于 2018-4-13 15:50:06

感谢分享

Miss_love 发表于 2020-12-29 17:10:48

支持分享
页: [1]
查看完整版本: 使用JMeter进行性能测试 —“Java请求”方式