jmeter压测rabbitmq的脚本准备
# jmeter压测rabbitmq的脚本准备
# 基于springboot生产、消费消息
# 代码
新建maven工程 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.</groupId>
<artifactId>rabbitmq-producer</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
</project>
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
ProducerApplication.java
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* \* Created with IntelliJ IDEA.
* \* User: yufeng
* \* Date: 2018/11/22
* \* Time: 上午11:25
* \* To change this template use File | Settings | File Templates.
* \* Description:
* \
*/
@EnableAutoConfiguration
@Configuration
public class ProducerApplication {
@Autowired
private ConnectionFactory connectionFactory;
@Autowired
private RabbitTemplate rabbitTemplate;
@Bean
ConnectionFactory connectionFactory(){
CachingConnectionFactory connectionFactory = new CachingConnectionFactory("IP",31105);
connectionFactory.setCacheMode(CachingConnectionFactory.CacheMode.CHANNEL);
connectionFactory.setChannelCacheSize(100);
connectionFactory.setVirtualHost("-dev");
connectionFactory.setChannelCheckoutTimeout(10000);
connectionFactory.setCloseTimeout(10000);
connectionFactory.setConnectionLimit(10000);
connectionFactory.setUsername("admin@");
connectionFactory.setPassword("admin");
return connectionFactory;
}
@Bean
public RabbitTemplate rabbitTemplate(){
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
return rabbitTemplate;
}
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(ProducerApplication.class);
RabbitTemplate rabbitTemplate = (RabbitTemplate) context.getBean("rabbitTemplate");
String message = "{\"count\":5,\"ackmode\":\"ack_requeue_true\",\"encoding\":\"auto\",\"truncate\":50000}";
String routingKey = "accounting-initAccount-key";
String exchange = "accounting-initAccount-exchange";
for (int i=0;i<10;i++){
rabbitTemplate.convertAndSend(exchange,routingKey,message);
}
System.exit(0);
}
}
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
ConsumerApplication.java
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
/**
* \* Created with IntelliJ IDEA.
* \* User: yufeng
* \* Date: 2018/11/22
* \* Time: 上午11:29
* \* To change this template use File | Settings | File Templates.
* \* Description:
* \
*/
@EnableAutoConfiguration
public class ConsumerApplication {
@Autowired
private ConnectionFactory connectionFactory;
@Autowired
private SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory;
@Autowired
private RabbitTemplate rabbitTemplate;
@Bean
SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory(){
SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory = new SimpleRabbitListenerContainerFactory();
simpleRabbitListenerContainerFactory.setConcurrentConsumers(50);
simpleRabbitListenerContainerFactory.setMaxConcurrentConsumers(100);
simpleRabbitListenerContainerFactory.setConnectionFactory(connectionFactory);
simpleRabbitListenerContainerFactory.setAcknowledgeMode(AcknowledgeMode.AUTO);
return simpleRabbitListenerContainerFactory;
}
@Bean
ConnectionFactory connectionFactory(){
CachingConnectionFactory connectionFactory = new CachingConnectionFactory("IP",31105);
connectionFactory.setCacheMode(CachingConnectionFactory.CacheMode.CHANNEL);
connectionFactory.setChannelCacheSize(100);
connectionFactory.setVirtualHost("-dev");
connectionFactory.setChannelCheckoutTimeout(10000);
connectionFactory.setCloseTimeout(10000);
connectionFactory.setConnectionLimit(10000);
connectionFactory.setUsername("admin@");
connectionFactory.setPassword("admin");
return connectionFactory;
}
// @RabbitListener(queues = "accounting-initAccount", containerFactory = "simpleRabbitListenerContainerFactory")
// public void onMessage(String message){
// System.out.printf("message is ->"+message+"\n");
// }
@Bean
public RabbitTemplate rabbitTemplate(){
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
return rabbitTemplate;
}
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(ConsumerApplication.class);
RabbitTemplate rabbitTemplate = (RabbitTemplate) context.getBean("rabbitTemplate");
for (int i=0;i<10;i++){
rabbitTemplate.receiveAndConvert("accounting-initAccount");
}
System.exit(0);
}
}
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
# 打jar包
pom.xml增加如下配置可以用mvn clean build
,来打带依赖的jar包
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
2
3
4
5
6
7
8
9
10
11
jar xvf test.jar
命令解压jar包,BOOT-INF/lib
目录下即可得到依赖的jar包。
# java请求编写
新建java工程,复制以上得到的jar包,和jmeter根目录下的lib目录下的jar包,到该java工程lib目录下,并添加依赖。
InitTemplate.java
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* \* Created with IntelliJ IDEA.
* \* User: yufeng
* \* Date: 2018/11/22
* \* Time: 上午11:25
* \* To change this template use File | Settings | File Templates.
* \* Description:
* \
*/
@EnableAutoConfiguration
@Configuration
public class InitTemplate {
@Autowired
private ConnectionFactory connectionFactory;
@Autowired
private static RabbitTemplate rabbitTemplate;
private static ApplicationContext context;
@Bean
ConnectionFactory connectionFactory(){
CachingConnectionFactory connectionFactory = new CachingConnectionFactory("IP",31105);
connectionFactory.setCacheMode(CachingConnectionFactory.CacheMode.CHANNEL);
connectionFactory.setChannelCacheSize(100);
connectionFactory.setVirtualHost("-dev");
connectionFactory.setChannelCheckoutTimeout(10000);
connectionFactory.setCloseTimeout(10000);
connectionFactory.setConnectionLimit(10000);
connectionFactory.setUsername("admin@");
connectionFactory.setPassword("admin");
return connectionFactory;
}
@Bean
public RabbitTemplate rabbitTemplate(){
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
return rabbitTemplate;
}
public static synchronized RabbitTemplate getTemplate(){
if(InitTemplate.context == null){
InitTemplate.context = SpringApplication.run(InitTemplate.class);
}
if(InitTemplate.rabbitTemplate == null){
InitTemplate.rabbitTemplate = (RabbitTemplate) context.getBean("rabbitTemplate");
}
return InitTemplate.rabbitTemplate;
}
public static void main(String[] args) {
// ApplicationContext context = SpringApplication.run(InitTemplate.class);
// RabbitTemplate rabbitTemplate = (RabbitTemplate) context.getBean("rabbitTemplate");
RabbitTemplate rabbitTemplate = InitTemplate.getTemplate();
String message = "{\"count\":5,\"ackmode\":\"ack_requeue_true\",\"encoding\":\"auto\",\"truncate\":50000}";
String routingKey = "accounting-initAccount-key";
String exchange = "accounting-initAccount-exchange";
for (int i=0;i<10;i++){
rabbitTemplate.convertAndSend(exchange,routingKey,message);
// rabbitTemplate.receiveAndConvert("accounting-initAccount");
}
System.exit(0);
}
}
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
JmeterRabbitmqConsumer.java
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* \* Created with IntelliJ IDEA.
* \* User: yufeng
* \* Date: 2018/11/22
* \* Time: 下午2:03
* \* To change this template use File | Settings | File Templates.
* \* Description:
* \
*/
public class JmeterRabbitmqConsumer extends AbstractJavaSamplerClient {
private static final Logger logger = LoggerFactory.getLogger(JmeterRabbitmqProducer.class);
private String queueName;
/**
* 这个方法是用来自定义java方法入参的
* params.addArgument("num1","");表示入参名字叫num1,默认值为空。
* @return
*/
@Override
public Arguments getDefaultParameters() {
Arguments params = new Arguments();
params.addArgument("queueName","accounting-initAccount");
return params;
}
/**
* 每个线程测试前执行一次,做一些初始化工作
* 获取输入的参数,赋值给变量,参数也可以在下面的runTest方法中获取,这里是为了展示该方法的作用
* @param arg0
*/
@Override
public void setupTest(JavaSamplerContext arg0) {
queueName = arg0.getParameter("queueName");
}
/**
* 真正执行逻辑的方法
* @param arg0
* @return
*/
@Override
public SampleResult runTest(JavaSamplerContext arg0) {
SampleResult sr = new SampleResult();
sr.setResponseData("消费消息;","utf-8");
logger.info("消费消息!!!");
try {
// jmeter 开始统计响应时间标记
sr.sampleStart();
InitTemplate.getTemplate().receiveAndConvert(queueName);
// 通过下面的操作就可以将被测方法的响应输出到Jmeter的察看结果树中的响应数据里面了。
sr.setResponseData("结果是:消费消息成功", "utf-8");
logger.info("消费消息结束!!!");
sr.setDataType(SampleResult.TEXT);
//设置响应执行成功
sr.setSuccessful(true);
} catch (Throwable e) {
//有异常,执行失败
sr.setSuccessful(false);
e.printStackTrace();
} finally {
// jmeter 结束统计响应时间标记
sr.sampleEnd();
}
return sr;
}
/**
* 测试结束后调用
* @param arg0
*/
@Override
public void teardownTest(JavaSamplerContext arg0) {
}
/**
* main方法测试程序是否可用,打包时 注释掉
* @param args
*/
public static void main(String[] args) {
// ApplicationContext context = SpringApplication.run(ConsumerApplication.class);
// RabbitTemplate rabbitTemplate = (RabbitTemplate) context.getBean("rabbitTemplate");
//
// for (int i=0;i<10;i++){
// rabbitTemplate.receiveAndConvert("accounting-initAccount");
// }
// System.exit(0);
// 测试
Arguments params = new Arguments();
params.addArgument("queueName","accounting-initAccount");
JavaSamplerContext arg0 = new JavaSamplerContext(params);
JmeterRabbitmqConsumer test = new JmeterRabbitmqConsumer();
test.setupTest(arg0);
test.runTest(arg0);
test.teardownTest(arg0);
System.exit(0);
}
}
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
JmeterRabbitmqProducer.java
import jodd.log.Logger;
import jodd.log.LoggerFactory;
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;
/**
* \* Created with IntelliJ IDEA.
* \* User: yufeng
* \* Date: 2018/11/22
* \* Time: 下午1:45
* \* To change this template use File | Settings | File Templates.
* \* Description:
* \
*/
public class JmeterRabbitmqProducer extends AbstractJavaSamplerClient {
private static final Logger logger = LoggerFactory.getLogger(JmeterRabbitmqConsumer.class);
private String message ;
private String routingKey;
private String exchange;
/**
* 这个方法是用来自定义java方法入参的
* params.addArgument("num1","");表示入参名字叫num1,默认值为空。
* @return
*/
@Override
public Arguments getDefaultParameters() {
Arguments params = new Arguments();
// params.addArgument("message","{\"count\":5,\"ackmode\":\"ack_requeue_true\",\"encoding\":\"auto\",\"truncate\":50000}");
params.addArgument("routingKey","accounting-initAccount-key");
params.addArgument("exchange","accounting-initAccount-exchange");
return params;
}
/**
* 每个线程测试前执行一次,做一些初始化工作
* 获取输入的参数,赋值给变量,参数也可以在下面的runTest方法中获取,这里是为了展示该方法的作用
* @param arg0
*/
@Override
public void setupTest(JavaSamplerContext arg0) {
// message = arg0.getParameter("message");
routingKey = arg0.getParameter("routingKey");
exchange = arg0.getParameter("exchange");
}
/**
* 真正执行逻辑的方法
* @param arg0
* @return
*/
@Override
public SampleResult runTest(JavaSamplerContext arg0) {
SampleResult sr = new SampleResult();
sr.setResponseData("生产消息;","utf-8");
logger.info("生产消息!!!");
try {
// jmeter 开始统计响应时间标记
sr.sampleStart();
InitTemplate.getTemplate().convertAndSend(exchange,routingKey,"{\"count\":5,\"ackmode\":\"ack_requeue_true\",\"encoding\":\"auto\",\"truncate\":50000}");
// 通过下面的操作就可以将被测方法的响应输出到Jmeter的察看结果树中的响应数据里面了。
sr.setResponseData("结果是:生产消息成功", "utf-8");
logger.info("生产消息结束!!!");
sr.setDataType(SampleResult.TEXT);
//设置响应执行成功
sr.setSuccessful(true);
} catch (Throwable e) {
//有异常,执行失败
sr.setSuccessful(false);
e.printStackTrace();
} finally {
// jmeter 结束统计响应时间标记
sr.sampleEnd();
}
return sr;
}
/**
* 测试结束后调用
* @param arg0
*/
@Override
public void teardownTest(JavaSamplerContext arg0) {
}
/**
* main方法测试程序是否可用,打包时 注释掉
* @param args
*/
public static void main(String[] args) {
// ApplicationContext context = SpringApplication.run(ProducerApplication.class);
// RabbitTemplate rabbitTemplate = (RabbitTemplate) context.getBean("rabbitTemplate");
//
// String message = "{\"count\":5,\"ackmode\":\"ack_requeue_true\",\"encoding\":\"auto\",\"truncate\":50000}";
// String routingKey = "accounting-initAccount-key";
// String exchange = "accounting-initAccount-exchange";
// for (int i=0;i<10;i++){
// rabbitTemplate.convertAndSend(exchange,routingKey,message);
// }
// System.exit(0);
// 测试
Arguments params = new Arguments();
// params.addArgument("message","{\"count\":5,\"ackmode\":\"ack_requeue_true\",\"encoding\":\"auto\",\"truncate\":50000}");
params.addArgument("routingKey","accounting-initAccount-key");
params.addArgument("exchange","accounting-initAccount-exchange");
JavaSamplerContext arg0 = new JavaSamplerContext(params);
JmeterRabbitmqProducer test = new JmeterRabbitmqProducer();
test.setupTest(arg0);
test.runTest(arg0);
test.teardownTest(arg0);
System.exit(0);
}
}
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
# 打jar包
创建一个java普通工程
1.点击Project创建一个Module
2.选择jdk,选择javaEE,点击next
3.输入项目名,点击Finish
添加依赖jar包
1.点击File ->Project Structure...
2.选择jar包,确认就可以了
将程序打成jar包
1.点击File ->Project Structure...->Artifacts
2.选择要打包的程序
3.打包程序 Build ->Build Artifacts...
4.点击屏幕中间出现的那个小框就可以了
参考
https://blog.csdn.net/qq_34021712/article/details/78871739
# jmeter运行
复制springboot的依赖jar包,复制java工程打的jar包,然后放在jmeter_home/lib/ext下面。然后就可以添加java请求了
Backend Listener
# 总结
实际上很多java项目都是基于springboot来完成,结合springboot的代码来完成jmeter的java请求,对于解决很多问题都有借鉴意义。
rabbitmq服务是其它服务通过rpc来链接的,采用http的方式不能模拟这种场景下的压力状况。通过java请求,对ApplicationContext、RabbitTemplate进行单例、并对InitTemplate.getTemplate()静态方法加锁,可以复用连接,可以完成压测脚本的编写。
# jar压缩和解压
压缩包: jar cvf filename.jar a.class b.class: 压缩指定文件; jar cvf weibosdkcore.jar *: 全部压缩;
解压包: jar xvf test.jar