Jmeter测试Java Request Sampler

为了压测一个Java class方法,jmeter上导入弄了好久,记录一下遇到的坑

整体思路和网上能搜到的基本一样,但网上打包基本都是通过Export或者Build Artifacts来进行打包,这个地方我也折腾了好久,最后直接通过maven来打的包

1:Jmeter里Java request和之前发送kafka消息的地方一样,而此处Classname能够切换成我们的测试类,要想Jmeter能够识别,必定必须要满足其约定的条件

NewImage

2:Jmeter提供交互有AbstractJavaSamplerClient类,以及JavaSamplerClient接口,因此只需要继承AbstractJavaSamplerClient或者实现JavaSamplerClient即可,首先添加依赖

<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_java</artifactId>
<version>4.0</version>
</dependency>

3:继承类或者实现接口后,必须重写方法

public Arguments getDefaultParameters();设置可用参数及的默认值;
public void setupTest(JavaSamplerContext arg0):每个线程测试前执行一次,做一些初始化工作;
public SampleResult runTest(JavaSamplerContext arg0):开始测试,从arg0参数可以获得参数值;
public void teardownTest(JavaSamplerContext arg0):测试结束时调用;

4:比如要测试的方法

public int sum(int a, int b) {
return a + b;
}

5:最终jmeter测试这个方法,要传入两个参数,a和b,默认显示为空

@Override
public Arguments getDefaultParameters() {
Arguments params = new Arguments();
params.addArgument("a", "");
params.addArgument("b", "");
return params;
}

6:每个线程执行之前,进行初始化,获取参数的值

@Override
public void setupTest(JavaSamplerContext arg0) {
a = arg0.getParameter("a");
b = arg0.getParameter("b");
}

7:执行测试,sampleStar和sampleEnd开始和结束响应时间的标记,中间就是测试方法的执行

@Override
public SampleResult runTest(JavaSamplerContext arg0) {
SampleResult sr = new SampleResult();
sr.setSamplerData("参数a:" + a + "\n参数b:" + b);
logger.info("参数a:{} 参数b:{}", a, b);

try {
sr.sampleStart();

int sum = sum(Integer.valueOf(a), Integer.valueOf(b));

sr.setResponseData("结果是:" + sum, "utf-8");
logger.info("结果是:{}", sum);
sr.setDataType(SampleResult.TEXT);
sr.setSuccessful(true);
} catch (Throwable e) {
sr.setSuccessful(false);
e.printStackTrace();
} finally {
sr.sampleEnd();
}
return sr;
}

8:测试结束完调用的内容

@Override
public void teardownTest(JavaSamplerContext arg0) {
}

9:这时候可以简单弄一个main函数,或者断言来进行测试一下

public static void main(String[] args) {
Arguments params = new Arguments();
params.addArgument("a", "1");
params.addArgument("b", "2");
JavaSamplerContext arg0 = new JavaSamplerContext(params);
App app = new App();
app.setupTest(arg0);
app.runTest(arg0);
app.teardownTest(arg0);
}

但打包的时候可以注释掉,反正没用,完成内容如下:

package com.lihuia;

import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.protocol.java.test.JavaTest;
import org.apache.jmeter.samplers.SampleResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Hello world!
*/


public class App implements JavaSamplerClient {

private static final Logger logger = LoggerFactory.getLogger(JavaTest.class);


private String a;
private String b;

public int sum(int a, int b) {
return a + b;
}

@Override
public Arguments getDefaultParameters() {
Arguments params = new Arguments();
params.addArgument("a", "");
params.addArgument("b", "");
return params;
}

@Override
public void setupTest(JavaSamplerContext arg0) {
a = arg0.getParameter("a");
b = arg0.getParameter("b");
}

@Override
public SampleResult runTest(JavaSamplerContext arg0) {
SampleResult sr = new SampleResult();
sr.setSamplerData("参数a:" + a + "\n参数b:" + b);
logger.info("参数a:{} 参数b:{}", a, b);

try {
sr.sampleStart();

int sum = sum(Integer.valueOf(a), Integer.valueOf(b));

sr.setResponseData("结果是:" + sum, "utf-8");
logger.info("结果是:{}", sum);
sr.setDataType(SampleResult.TEXT);
sr.setSuccessful(true);
} catch (Throwable e) {
sr.setSuccessful(false);
e.printStackTrace();
} finally {
sr.sampleEnd();
}
return sr;
}


@Override
public void teardownTest(JavaSamplerContext arg0) {
logger.info("com.lihua.App.teardown");
}


// public static void main(String[] args) {
// Arguments params = new Arguments();
// params.addArgument("a", "1");
// params.addArgument("b", "2");
// JavaSamplerContext arg0 = new JavaSamplerContext(params);
// App app = new App();
// app.setupTest(arg0);
// app.runTest(arg0);
// app.teardownTest(arg0);
// }
}

10:在测试的时候,会报一个log4j2的错误

error statuslogger no log4j2 configuration file found. using default config

经确认是引入ApacheJMeter_java的原因

google了一把,可以在classpath里新增下面log4j2.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>


<configuration status="error">
<!--先定义所有的appender-->
<appenders>
<!--这个输出控制台的配置-->
<Console name="Console" target="SYSTEM_OUT">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/>
<!--这个都知道是输出日志的格式-->
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
</Console>
<!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用-->
<File name="log" fileName="log/test.log" append="false">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
</File>


<!--这个会打印出所有的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFile" fileName="logs/app.log"
filePattern="log/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/>
<SizeBasedTriggeringPolicy size="50MB"/>
</RollingFile>
</appenders>
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
<loggers>
<!--建立一个默认的root的logger-->
<root level="trace">
<appender-ref ref="RollingFile"/>
<appender-ref ref="Console"/>
</root>


</loggers>
</configuration>

11:下面可以进行打包,这里要注意的是,要打的包是runnable的jar包,而不是一个文件包,网上大多是直接File->Project Structure里完成配置

NewImage

接着通过Build Artifacts来完成打包;但是我打出来的包,放到jmeter里没有识别出来过

直接通过maven进行打包,因为是runnable包,因此必须带依赖

pom文件里新增plugin,指明mainClass

<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<!-- 此处指定main方法入口的class -->
<mainClass>com.lihuia.App</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>

然后mvn package进行打包,可以先将main函数注释去掉,确认打出来的包可以执行

$ java -jar target/hello-1.0-SNAPSHOT-jar-with-dependencies.jar
18:17:16.059 WARN  org.apache.jmeter.util.JMeterUtils 794 getPropDefault - Exception 'null' occurred when fetching String property:'sampleresult.default.encoding', defaulting to: ISO-8859-1
18:17:16.062 WARN  org.apache.jmeter.util.JMeterUtils 730 getPropDefault - Exception 'null' occurred when fetching boolean property:'sampleresult.timestamp.start', defaulting to: false
18:17:16.062 WARN  org.apache.jmeter.util.JMeterUtils 730 getPropDefault - Exception 'null' occurred when fetching boolean property:'sampleresult.useNanoTime', defaulting to: true
18:17:16.062 WARN  org.apache.jmeter.util.JMeterUtils 703 getPropDefault - Exception 'null' occurred when fetching int property:'sampleresult.nanoThreadSleep', defaulting to: 5000
18:17:16.063 INFO  org.apache.jmeter.samplers.SampleResult 140  - Note: Sample TimeStamps are END times
18:17:16.063 INFO  org.apache.jmeter.samplers.SampleResult 142  - sampleresult.default.encoding is set to ISO-8859-1
18:17:16.064 INFO  org.apache.jmeter.samplers.SampleResult 143  - sampleresult.useNanoTime=true
18:17:16.064 INFO  org.apache.jmeter.samplers.SampleResult 144  - sampleresult.nanoThreadSleep=5000
18:17:16.065 INFO  com.lihuia.App 47 runTest - 参数a:1 参数b:2
18:17:16.065 INFO  com.lihuia.App 55 runTest - 结果是:3

12:将jar包copy到jmeter的lib/ext目录下,加载之后重新打开jmeter

NewImage

13:自定义参数执行该方法的测试

NewImage

OVER

发表评论