RocketMQ普通消息的简单使用demo
官方文档:http://rocketmq.apache.org/docs/simple-example/
第一步:pom文件添加依赖
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.6.0</version>
</dependency>
第二步:添加配置文件
配置文件里面的配置也可以直接写到配置类里面,因为使用的是原生api,springboot并不会
############### mq相关配置,使用的原生api,会在配置类里读取该配置 ###############
############### 消费者 ###########
# 是否开启自动配置
rocketmq.consumer.isOnOff=on
# 消费者gorup名称,一个消费者一个groupName,保证唯一性
rocketmq.consumer.groupName=consumer_01
# mq的nameserver地址
rocketmq.consumer.namesrvAddr=127.0.0.1:9876
# 消费者订阅的主题topic和tags(*标识订阅该主题下所有的tags),格式: topic~tag1||tag2||tags3;
rocketmq.consumer.topics=TestTopic~TestTag||abcTag;MyTopic~*
# 消费者线程数据量
rocketmq.consumer.consumeThreadMin=5
rocketmq.consumer.consumeThreadMax=10
# 设置一次消费信息的条数,默认1
rocketmq.consumer.consumeMessageBatchMaxSize=1
############### 生产者 ###########
# 是否开启自动配置
rocketmq.producer.isOnOff=on
# 生产者gorup名称,一个消生产者一个groupName,保证唯一性
rocketmq.producer.groupName=producer_01
# mq的nameserver地址
rocketmq.producer.namesrvAddr=127.0.0.1:9876
# 消息最大长度 默认 1024 * 4 (4M)
rocketmq.producer.maxMessageSize = 4096
# 发送消息超时时间,默认 3000
rocketmq.producer.sendMsgTimeOut=3000
# 发送消息失败重试次数,默认2
rocketmq.producer.retryTimesWhenSendFailed=2
第四步:编写生产者
两个消费者
package com.zhh.demo.commons.mq;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
/**
* mq消费者1
*/
@Component
public class MQConsumeMsgListenerProcessor implements MessageListenerConcurrently {
public static final Logger log = LoggerFactory.getLogger(MQConsumeMsgListenerProcessor.class);
/**
* 默认msg里只有一条消息,可以通过设置consumeMessageBatchMaxSize参数来批量接收消息
* 不要抛异常,如果没有return CONSUME_SUCCESS ,consumer会重新消费该消息,直到return CONSUME_SUCCESS
* @param msgList
* @param consumeConcurrentlyContext
* @return
*/
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgList, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
if (CollectionUtils.isEmpty(msgList)) {
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
MessageExt messageExt = msgList.get(0);
log.info("MQ消费者1,接收到的消息为:{}", messageExt.toString());
try {
String body = new String(messageExt.getBody(), "utf-8");
log.info("MQ消费者1, topic={}, tags={}, 消息内容={}", messageExt.getTopic(),messageExt.getTags(),body);
} catch (Exception e) {
log.error("MQ消费者1,获取消息内容异常{}",e);
}
// ACK 返回消费状态;CONSUME_SUCCESS 消费成功,RECONSUME_LATER 消费失败,需要稍后重新消费
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
}
package com.zhh.demo.commons.mq;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
/**
* mq消费者2
*/
@Component
public class MQConsumeMsgListenerProcessor2 implements MessageListenerConcurrently {
public static final Logger log = LoggerFactory.getLogger(MQConsumeMsgListenerProcessor2.class);
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgList, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
if (CollectionUtils.isEmpty(msgList)) {
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
MessageExt messageExt = msgList.get(0);
log.info("MQ消费者2,接收到的消息为:{}", messageExt.toString());
try {
String body = new String(messageExt.getBody(), "utf-8");
log.info("MQ消费者2, topic={}, tags={}, 消息内容={}", messageExt.getTopic(),messageExt.getTags(),body);
} catch (Exception e) {
log.error("MQ消费者2,获取消息内容异常{}",e);
}
// ACK 返回消费状态;CONSUME_SUCCESS 消费成功,RECONSUME_LATER 消费失败,需要稍后重新消费
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
}
第四步:编写配置类,监听编写的消费者
可以配置多个生产者和消费者
package com.zhh.demo.commons.mq.config;
import com.zhh.demo.commons.mq.MQConsumeMsgListenerProcessor;
import com.zhh.demo.commons.mq.MQConsumeMsgListenerProcessor2;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* mq生产者消费者配置
*/
@Configuration
public class RocketMqConfig {
private static final Logger log = LoggerFactory.getLogger(RocketMqConfig.class);
@Value("${rocketmq.consumer.groupName}")
private String groupName;
@Value("${rocketmq.consumer.namesrvAddr}")
private String namesrvAddr;
@Value("${rocketmq.consumer.topics}")
private String topics;
@Value("${rocketmq.consumer.consumeThreadMin}")
private Integer consumeThreadMin;
@Value("${rocketmq.consumer.consumeThreadMax}")
private Integer consumeThreadMax;
@Value("${rocketmq.consumer.consumeMessageBatchMaxSize}")
private Integer consumeMessageBatchMaxSize;
// 生产者
@Value("${rocketmq.producer.maxMessageSize}")
private Integer maxMessageSize;
@Value("${rocketmq.producer.sendMsgTimeOut}")
private Integer sendMsgTimeOut;
@Value("${rocketmq.producer.retryTimesWhenSendFailed}")
private Integer retryTimesWhenSendFailed;
// 消费者消息处理对象1
@Autowired
private MQConsumeMsgListenerProcessor consumeMsgListenerProcessor;
// 消费者消息处理对象2
@Autowired
private MQConsumeMsgListenerProcessor2 consumeMsgListenerProcessor2;
/**
* mq 配置第1个消费者
* @return
*/
@Bean
public DefaultMQPushConsumer consumer1(){
log.info("consumer1 正在创建...");
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(groupName);
consumer.setNamesrvAddr(namesrvAddr);
consumer.setConsumeThreadMin(consumeThreadMin);
consumer.setConsumeThreadMax(consumeThreadMax);
consumer.setConsumeMessageBatchMaxSize(consumeMessageBatchMaxSize);
// 设置监听
consumer.registerMessageListener(consumeMsgListenerProcessor);
/**
* 设置consumer第一次启动是从队列头部开始还是队列尾部开始
* 如果不是第一次启动,那么按照上次消费的位置继续消费
*/
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
// 设置消费模型,集群还是广播,默认为集群
// consumer.setMessageModel(MessageModel.CLUSTERING);
try {
// 设置该消费者订阅的主题和tag,如果订阅该主题下的所有tag,则使用*,
String[] topicArr = topics.split(";");
for (String tag : topicArr) {
String[] tagArr = tag.split("~");
consumer.subscribe(tagArr[0], tagArr[1]);
}
consumer.start();
log.info("consumer1 创建成功 groupName={}, topics={}, namesrvAddr={}",groupName,topics,namesrvAddr);
} catch (MQClientException e) {
log.error("consumer1 创建失败!");
}
return consumer;
}
/**
* mq 配置第2个消费者
* @return
*/
@Bean
public DefaultMQPushConsumer consumer2() {
log.info("consumer2 正在创建....");
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group2");
consumer.setNamesrvAddr(namesrvAddr);
consumer.setConsumeThreadMin(consumeThreadMin);
consumer.setConsumeThreadMax(consumeThreadMax);
consumer.setConsumeMessageBatchMaxSize(consumeMessageBatchMaxSize);
// 设置监听
consumer.registerMessageListener(consumeMsgListenerProcessor2);
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
try {
// 设置该消费者订阅的主题和tag,如果订阅该主题下的所有tag,则使用*,
consumer.subscribe("LogTopic", "LogTag");
consumer.start();
log.info("consumer2 创建成功 groupName={}, topics={}, namesrvAddr={}",groupName,topics,namesrvAddr);
} catch (MQClientException e) {
log.error("consumer2 创建失败!",e);
}
return consumer;
}
/**
* mq 生产者配置
* @return
*/
@Bean
public DefaultMQProducer defaultProducer() throws MQClientException {
log.info("defaultProducer 正在创建...");
DefaultMQProducer producer = new DefaultMQProducer(groupName);
producer.setNamesrvAddr(namesrvAddr);
producer.setVipChannelEnabled(false);
producer.setMaxMessageSize(maxMessageSize);
producer.setSendMsgTimeout(sendMsgTimeOut);
producer.setRetryTimesWhenSendAsyncFailed(retryTimesWhenSendFailed);
producer.start();
log.info("defaultProducer 正在创建成功");
return producer;
}
}
第五步:编写测试代码
package com.zhh.demo.webs.controller;
import com.alibaba.fastjson.JSON;
import com.zhh.demo.domain.User;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@CrossOrigin("*")
@Controller
@RequestMapping("/mq")
public class MqController {
private static final Logger log = LoggerFactory.getLogger(UserController.class);
@Autowired
private DefaultMQProducer defaultMQProducer;
@ResponseBody
@RequestMapping("/send")
public Object sedMq(String msg,String type) {
log.info("入参msg:{},type:{}",msg,type);
Message sendMsg;
// 发送消息到对应的topic
if ("1".equals(type)){
sendMsg = new Message("TestTopic", "TestTag", msg.getBytes());
}else if ("2".equals(type)){
sendMsg = new Message("TestTopic", "abcTag", msg.getBytes());
/**
* 延时消息,设置延时级别
* rocketMQ 支持定时消息,但是不支持任意时间精度,仅支持特定的 level,例如定时1s, 5s, 10s, 1m 等。其中,level=0 级表示不延时,level=1 表示 1 级延时,level=2 表示 2 级延时,以此类推
* 3表示10秒延时
*/
sendMsg.setDelayTimeLevel(3);
}else if ("3".equals(type)){
sendMsg = new Message("LogTopic", "LogTag", msg.getBytes());
}else {
sendMsg = new Message("MyTopic", "allTag", msg.getBytes());
}
// 默认3秒超时
try {
SendResult sendResult = defaultMQProducer.send(sendMsg);
log.info("消息发送到mq成功:{}", sendResult.toString());
} catch (Exception e) {
e.printStackTrace();
}
return "消息发送mq成功";
}
}