ITest

jmeter-java请求-dubbo

2020-12-23

dubbo 接口压力测试脚本编写

一、创建maven工程

pom.xml里导入jmeter依赖及相应服务的依赖

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_java</artifactId>
<version>4.0</version>
</dependency>
<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_core</artifactId>
<version>4.0</version>
</dependency>

二、编写dubbo连接class DubboSampleClient

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package dubbo;

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.utils.ReferenceConfigCache;
import com.alibaba.fastjson.JSON;
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 org.apache.log4j.Logger;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
* 基类 Created by binli on 2015-12-15.
*/
public abstract class DubboSampleClient<T> extends AbstractJavaSamplerClient {
private static Logger logger = Logger.getLogger(DubboSampleClient.class);
/**
* privider实例
*/
private T instance;

/**
*
* @return
*/
protected String getInterfaceName() {
String interfaceName = getSuperClassGenricType(getClass(), 0).getName();
System.out.println(interfaceName);
return interfaceName;
}

/**
* 拿到provider的实例
*
* @return
*/
protected T getInstance() {
return instance;
}

/**
* 初始化test
*
* @param context
*/
@Override
public void setupTest(JavaSamplerContext context) {
super.setupTest(context);
// 当前应用配置
ApplicationConfig application = new ApplicationConfig();
application.setName(context.getParameter("consumerName1", "jmeter-dubbo-test1"));

// 连接注册中心配置
RegistryConfig registry = new RegistryConfig();
registry.setAddress(context.getParameter("zkAddress",
"zktestserver1.wacai.info:22181,zktestserver2.wacai.info:22181,zktestserver3.wacai.info:22181"));
registry.setGroup(context.getParameter("dubboGroup", "dubbo_test"));
registry.setProtocol("zookeeper");
registry.setClient("zkclient");

/**
* 注意:ReferenceConfig为重对象,内部封装了与注册中心的连接,以及与服务提供方的连接
* 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏
*/
ReferenceConfig<T> reference = new ReferenceConfig<T>(); reference.setApplication(application);
/**
* 多个注册中心可以用setRegistries()
* */

reference.setRegistry(registry);
reference.setInterface(getInterfaceName());
reference.setTimeout(50000);
reference.setUrl(context.getParameter("url"));
String version = context.getParameter("version");
if(null!=version&&!"".equals(version)){
reference.setVersion("3.0");
}
String zkAddress = context.getParameter("zkAddress");
if (null != zkAddress) {
if (zkAddress.startsWith("dubbo")) {
reference.setUrl(context.getParameter("zkAddress"));
}
ReferenceConfigCache cache = ReferenceConfigCache.getCache();
instance = cache.get(reference);
}

}

/**
* 返回给jmeter默认可设置的参数
*
* @return
*/
@Override
public Arguments getDefaultParameters() {
Arguments args = new Arguments();
args.addArgument("consumerName", "jmeter-dubbo-test");
args.addArgument("dubboGroup", "dubbo_test");
args.addArgument("url", "");
args.addArgument("zkAddress",
"zktestserver1.wacai.info:22181,zktestserver2.wacai.info:22181,zktestserver3.wacai.info:22181");
return args;
}

/**
* 获得泛型
*
* @param clazz
* @param index
* @return
*/
private Class<Object> getSuperClassGenricType(final Class clazz, final int index) {

Type genType = clazz.getGenericSuperclass();

if (!(genType instanceof ParameterizedType)) {
return Object.class;
}
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();

if (index >= params.length || index < 0) {
return Object.class;
}
if (!(params[index] instanceof Class)) {
return Object.class;
}

return (Class) params[index];
}

public SampleResult sampleRun(JavaSamplerContext jsc, Action a) {
SampleResult result = new SampleResult();
result.sampleStart(); // start stopwatch
Object res = null;
try {
res = a.preform();
} catch (Exception e) {
// e.printStackTrace();
logger.error(e.getMessage());
}
System.out.println(JSON.toJSON(res));
logger.info("res-----:"+JSON.toJSON(res));
if (null != res) {
result.sampleEnd(); // stop stopwatch
result.setSuccessful(true);
result.setResponseData(JSON.toJSONString(res), "utf-8");
result.setResponseMessage(JSON.toJSONString(res));
result.setResponseCodeOK(); // 200 code
} else {
result.sampleEnd(); // stop stopwatch
result.setSuccessful(false);
}
return result;

}

/**
* The Action Class is for making the Demo View Custom Code
*/
public interface Action {
public Object preform();
}

}

DubboSampleClient 类对dubbo连接做了封装 dubbo参数要在这里配置,此类在测试项目中有介绍,这里不过多描述。

三、编写测试class

public class PushByPushIdTest extends DubboSampleClient{方法体} 该类必须继承DubboSampleClient()

  • 1、编写界面参数 命名固定为getDefaultParameters()方法

    参数类型全部为string类型,如果后面要用其他类型参数传入,此时需要转换。

1
2
3
4
5
6
7
8
 public Arguments getDefaultParameters() {
Arguments args = super.getDefaultParameters();
//此处请添加你们需要动态变化的参数
args.addArgument("pushId", "abde7537e79039b72cea2e340ecdeb10");
args.addArgument("content","byPushId 压力测试");
args.addArgument("url","");
return args;
}
  • 2、编写数据处理逻辑

    命名固定为runTest(JavaSamplerContext jsc)方法 并且要有类型为SampleResult返回值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public SampleResult  runTest(JavaSamplerContext jsc) {
SampleResult sr = new SampleResult();
return super.sampleRun(jsc, ()->{
try {
/Sample 开始 记录开始时间
sr.sampleStart();
RequestParam requestParam = new RequestParam();
requestParam.setAppName("wcb");
requestParam.setExpiredTime(1L);
String plat = jsc.getParameter("platforms");
/将传入的string类型转成list
List<Integer> listplat = Arrays.asList(plat.split(","))
.stream().map(s -> Integer.parseInt(s.trim()))
.collect(Collectors.toList());
requestParam.setPlatforms(listplat);
requestParam.setPushId(jsc.getParameter("pushId"));
requestParam.setContent(jsc.getParameter("content"));
int mt = requestParam.setMsgType(mt);


Response<ErrorCode> result = getInstance().pushByPushId(requestParam);
sr.setSamplerData(result.getValue().getReason());
sr.setSuccessful(true);

}catch (Exception e){
sr.getResponseData();
sr.setSuccessful(false);
e.printStackTrace();

}finally {
sr.sampleEnd();
}
return sr;

});

}

四、main函数检查可行性(压测中此方法不是必要条件,主要用来检测)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(String args[]) {
Arguments argss = new Arguments();
argss.addArgument("pushId", "abde7537e79039b72cea2e340ecdeb10");
argss.addArgument("content","byPushId 压力测试");
argss.addArgument("url","www.baidu.com");
argss.addArgument("title","title 测试");
argss.addArgument("platforms","41");
argss.addArgument("msgType","1");
argss.addArgument("zkAddress",
"zktestserver1.wacai.info:22181,zktestserver2.wacai.info:22181,zktestserver3.wacai.info:22181");
JavaSamplerContext jsc = new JavaSamplerContext(argss);
PushByPushIdTest bqe = new PushByPushIdTest();
bqe.setupTest(jsc);
bqe.runTest(jsc);
}

五、jar包导入

  • 1、打成jar包 ,将打好的项目jar包放在jmeter/lib/ext下。
  • 2、执行mvn dependency:copy-dependencies下载工程依赖包,targer/dependecies 目录下为所以依赖包,
    完成后将依赖包全部放在jmeter/lib下 , 不得和lib已有的包冲突 ,如果冲突,删除所以已有jar包,然后放入所以依赖包。
  • 3、启动jmeter, 在java请求中理论会有包里的测试class, 没有则检查包及代码。

测试项目

此项目只参考去编写,不要使用本项目进行压测

git@git.caimi-inc.com:qiuhaitang/jmeterdubbotest.git