1.前言
由于公司项目中目前正在淘汰RabbitMQ全面使用RocketMQ,所以抽空整理了一些Rocket的常用的用法,写成了一个Demo,RocketMQ相比RabbitMQ的优势,个人认为就是在堆积处理方面非常的优秀,以及在顺序处理消息方面的写法特别的简单。
深入了解可以在gitlab上阅读相关的中文文档
https://github.com/apache/rocketmq/tree/master/docs/cn
2.DEMO
本次的Demo主要是根据RocketMQ 4.8.0 ,rocket-spring-boot-stater 2.2.0进行的测各种消息模式测试,主要是普通,多TAG,顺序,事务,发送并相应生产消息模式
2.1常量定义
public class TestMQConstant {
public static final String FORMAT = "%s:%s";
public static final String SYMBOL = "||";
public static final String TOPIC = "testTopic";
public static final String TAG_NORMAL = "normal";
public static final String CONSUMER_NORMAL = "consumerNormal";
public static final String TAG_ORDERLY = "orderly";
public static final String CONSUMER_ORDERLY = "consumerOrderly";
public static final String TAG_MULTI_FIRST = "multiFirst";
public static final String TAG_MULTI_SECOND = "multiSecond";
public static final String TAG_MULTI = TAG_MULTI_FIRST + SYMBOL + TAG_MULTI_SECOND;
public static final String CONSUMER_MULTI = "consumerMulti";
public static final String TAG_SEND_AND_RECEIVE = "sendAndReceive";
public static final String CONSUMER_SEND_AND_RECEIVE = "consumerSendAndReceive";
public static final String TAG_TRANSACTION = "transaction";
public static final String CONSUMER_TRANSACTION = "consumerTransaction";
public static final String SHARER_KEY_QUEUE_FIRST = "queueFirst";
public static final String SHARER_KEY_QUEUE_SECOND = "queueSecond";
private TestMQConstant() {
}
}
2.2 消息实体类定义
public class TestMessage {
private String field1;
private String field2;
private Boolean flag;
private String shareKey;
public String getShareKey() {
return shareKey;
}
public void setShareKey(String shareKey) {
this.shareKey = shareKey;
}
public String getField1() {
return field1;
}
public void setField1(String field1) {
this.field1 = field1;
}
public String getField2() {
return field2;
}
public void setField2(String field2) {
this.field2 = field2;
}
public Boolean getFlag() {
return flag;
}
public void setFlag(Boolean flag) {
this.flag = flag;
}
@Override
public String toString() {
return "TestMessage{" +
"field1='" + field1 + '\'' +
", field2='" + field2 + '\'' +
", flag=" + flag +
", shareKey='" + shareKey + '\'' +
'}';
}
}
public class TestReplyMessage {
private String message;
private int code;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
@Override
public String toString() {
return "TestReplyMessage{" +
"message='" + message + '\'' +
", code=" + code +
'}';
}
}
2.3 配置文件配置
2.3.1生产者
rocketmq.name-server=127.0.0.1:9876
rocketmq.producer.group=test-producer-group
rocketmq.producer.access-key=
rocketmq.producer.secret-key=
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>TestRocketMQProducer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>TestRocketMQProducer</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>1.5.8</version>
<executions>
<execution>
<id>generate-docs</id>
<phase>prepare-package</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>html</backend>
<doctype>book</doctype>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.5.RELEASE</version>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.3.2消费者
# rocketmq
rocketmq.name-server=127.0.0.1:9876
rocketmq.producer.access-key=
rocketmq.producer.secret-key=
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>TestRocketMQConsumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>TestRocketMQConsumer</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>1.5.8</version>
<executions>
<execution>
<id>generate-docs</id>
<phase>prepare-package</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>html</backend>
<doctype>book</doctype>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
3测试各类消费模式
3.1普通消费模式
3.1.1 生产者
@Resource
private RocketMQTemplate rocketMQTemplate;
@Test
void sendNormalMessage() {
List<TestMessage> dataList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
TestMessage testQueue1TestMessage1 = new TestMessage();
testQueue1TestMessage1.setField1(i + "");
dataList.add(testQueue1TestMessage1);
}
String destination = formatDestinationByTag(TAG_NORMAL);
for (TestMessage testMessage : dataList) {
rocketMQTemplate.syncSend(destination, testMessage);
}
}
3.1.2 消费者
@Service
@RocketMQMessageListener(
topic = TestMQConstant.TOPIC,
consumerGroup = TestMQConstant.CONSUMER_NORMAL,
selectorExpression = TestMQConstant.TAG_NORMAL,
consumeMode = ConsumeMode.CONCURRENTLY)
@Slf4j
public class TesNormalConsumer implements RocketMQListener<TestMessage> {
@Override
public void onMessage(TestMessage testMessage) {
log.info("进入了【普通消费者】:{}", testMessage);
}
}
3.2 有序的消费模式
3.2.1 生产者
@Test
void sendOrderlyMessage() throws InterruptedException {
List<TestMessage> queue1 = new ArrayList<>();
List<TestMessage> queue2 = new ArrayList<>();
for (int i = 0; i < 10; i++) {
TestMessage testQueue1TestMessage1 = new TestMessage();
testQueue1TestMessage1.setField1(String.valueOf(i));
testQueue1TestMessage1.setShareKey(SHARER_KEY_QUEUE_FIRST);
queue1.add(testQueue1TestMessage1);
TestMessage testQueue1TestMessage2 = new TestMessage();
testQueue1TestMessage2.setField2(String.valueOf(i));
testQueue1TestMessage2.setShareKey(SHARER_KEY_QUEUE_SECOND);
queue2.add(testQueue1TestMessage2);
}
String destination = formatDestinationByTag(TAG_ORDERLY);
Thread thread1 = new Thread(() -> {
for (TestMessage testMessage : queue1) {
rocketMQTemplate.syncSendOrderly(destination, testMessage, testMessage.getShareKey());
}
});
Thread thread2 = new Thread(() -> {
for (TestMessage testMessage : queue2) {
rocketMQTemplate.syncSendOrderly(destination, testMessage, testMessage.getShareKey());
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
3.2.2 消费者
@Service
@RocketMQMessageListener(
topic = TestMQConstant.TOPIC,
consumerGroup = TestMQConstant.CONSUMER_ORDERLY,
selectorExpression = TestMQConstant.TAG_ORDERLY,
consumeMode = ConsumeMode.ORDERLY)
@Slf4j
public class TestOrderlyConsumer implements RocketMQListener<TestMessage> {
private static final Random random = new Random();
@SneakyThrows
@Override
public void onMessage(TestMessage testMessage) {
log.info("进入了【顺序消费者】:{}", testMessage);
String shareKey = testMessage.getShareKey();
if (TestMQConstant.SHARER_KEY_QUEUE_FIRST.equals(shareKey) || TestMQConstant.SHARER_KEY_QUEUE_SECOND.equals(shareKey)) {
int randomInt = random.nextInt(100) + 1000;
log.info("随机睡眠:{}", randomInt);
Thread.sleep(randomInt);
}
log.info("睡眠结束:{}", testMessage);
}
}
3.3 多个Tag消费者模式
3.3.1 生产者
@Test
void sendMultiTagToSameConsumerMessage() {
TestMessage testQueue1TestMessage1 = new TestMessage();
testQueue1TestMessage1.setField1(TAG_MULTI_FIRST);
TestMessage testQueue1TestMessage2 = new TestMessage();
testQueue1TestMessage2.setField1(TAG_MULTI_SECOND);
String destination1 = formatDestinationByTag(TAG_MULTI_FIRST);
String destination2 = formatDestinationByTag(TAG_MULTI_SECOND);
rocketMQTemplate.syncSend(destination1, testQueue1TestMessage1);
rocketMQTemplate.syncSend(destination2, testQueue1TestMessage2);
}
3.3.2 消费者
@Service
@RocketMQMessageListener(
topic = TestMQConstant.TOPIC,
consumerGroup = TestMQConstant.CONSUMER_MULTI,
selectorExpression = TestMQConstant.TAG_MULTI,
consumeMode = ConsumeMode.CONCURRENTLY)
@Slf4j
public class TesMultiNormalConsumer implements RocketMQListener<TestMessage> {
@Override
public void onMessage(TestMessage testMessage) {
log.info("进入了【多个Tag的消费者】:tag{}", testMessage.getField1());
}
}
3.4 事务消费者模式
3.4.1生产者
@Test
void senTransactionMessage() throws InterruptedException {
TestMessage success = new TestMessage();
success.setField1(TAG_TRANSACTION);
success.setFlag(true);
senTransactionMessage(success);
TestMessage fail = new TestMessage();
fail.setField1(TAG_TRANSACTION);
fail.setFlag(false);
senTransactionMessage(fail);
TestMessage unknown = new TestMessage();
success.setField1(TAG_TRANSACTION);
success.setFlag(null);
senTransactionMessage(unknown);
Thread.sleep(30000);
}
private void senTransactionMessage(TestMessage success) {
String destination = formatDestinationByTag(TAG_TRANSACTION);
Message<TestMessage> build = MessageBuilder.withPayload(success).build();
TransactionSendResult transactionSendResult = rocketMQTemplate.sendMessageInTransaction(destination, build, success.getFlag());
System.out.println(transactionSendResult.toString());
}
3.4.2 消费者
@Service
@RocketMQMessageListener(
topic = TestMQConstant.TOPIC,
consumerGroup = TestMQConstant.CONSUMER_TRANSACTION,
selectorExpression = TestMQConstant.TAG_TRANSACTION,
consumeMode = ConsumeMode.CONCURRENTLY)
@Slf4j
public class TesTransactionConsumer implements RocketMQListener<TestMessage> {
@Override
public void onMessage(TestMessage message) {
log.info("进入了【事务消费者】:{}", message);
}
}
3.5 发送并相应模式
3.5.1 生产者
@Test
void sendAndReceiver() {
TestMessage testEntityTestMessage = new TestMessage();
testEntityTestMessage.setField1(TAG_SEND_AND_RECEIVE);
String destination = formatDestinationByTag(TAG_SEND_AND_RECEIVE);
TestReplyMessage testReplyMessage = rocketMQTemplate.sendAndReceive(destination, testEntityTestMessage, TestReplyMessage.class, 6000);
System.out.println(testReplyMessage);
}
3.5.2 消费者
@Service
@RocketMQMessageListener(
topic = TestMQConstant.TOPIC,
consumerGroup = TestMQConstant.CONSUMER_SEND_AND_RECEIVE,
selectorExpression = TestMQConstant.TAG_SEND_AND_RECEIVE,
consumeMode = ConsumeMode.CONCURRENTLY)
@Slf4j
public class TesSendAndReceiverConsumer implements RocketMQReplyListener<TestMessage, TestReplyMessage> {
@SneakyThrows
@Override
public TestReplyMessage onMessage(TestMessage message) {
log.info("进入了【发送并且响应的消费者】:{}", message);
log.info("正在消费...loading...");
Thread.sleep(3000);
TestReplyMessage testReplyMessage = new TestReplyMessage();
testReplyMessage.setMessage("消费成功");
testReplyMessage.setCode(0);
return testReplyMessage;
}
}
4 完整Maven代码下载路径
https://download.csdn.net/download/xuexi_deng/54839349