为了压测一个Java class方法,jmeter上导入弄了好久,记录一下遇到的坑
整体思路和网上能搜到的基本一样,但网上打包基本都是通过Export或者Build Artifacts来进行打包,这个地方我也折腾了好久,最后直接通过maven来打的包
1:Jmeter里Java request和之前发送kafka消息的地方一样,而此处Classname能够切换成我们的测试类,要想Jmeter能够识别,必定必须要满足其约定的条件
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里完成配置
接着通过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
13:自定义参数执行该方法的测试
OVER