spring 集成RocketMQ异步消费
点关注不迷路,欢迎再访!
精简博客内容,尽量已行业术语来分享。
努力做到对每一位认可自己的读者负责。
帮助别人的同时更是丰富自己的良机。
工作需要采用异步消费来实现生产者/消费者解耦:
方案1:采用传统schedule实现
方案2:使用RocketMQ实现
由于业务需要保证消费实时性,最终我们选择了本章知识RocketMQ
一.引入依赖
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.7.0</version>
</dependency>
二.mq.properties配置
rocketmq.consumerGroup=thConsumerGroup
rocketmq.namesrvAddr=ip1:port1;ip2:port2
rocketmq.topicTag=TAG1
rocketmq.topic=TestTopic1
#消费模式
rocketmq.consumeFromWhere=CONSUME_FROM_LAST_OFFSET
#传播行为
rocketmq.messageModel=CLUSTERING
三.创建topic命令
目录:rocketmq/bin
sh mqadmin updateTopic -n ip1:port1 -b ip2:port2-t TestTopic1
四.生产者
private final Log logger = LogFactory.getLog(getClass());
@Value("${rocketmq.namesrvAddr}")
private String namesrvAddr;
@Value("${rocketmq.consumerGroup}")
private String consumerGroup;
@Value("${rocketmq.topic}")
private String topic;
@Value("${rocketmq.topicTag}")
private String topicTag;
public void sendFileToMq(String fileid) throws IOException {
DefaultMQProducer producer = new DefaultMQProducer(consumerGroup);
producer.setNamesrvAddr(namesrvAddr);
producer.setVipChannelEnabled(true);
producer.setInstanceName(fileid);
SendResult sendResult;
try {
producer.start();
Message msg = new Message(topic, topicTag, fileid, fileid.getBytes());
sendResult = producer.send(msg);
logger.info("消息内容:=="+sendResult);
logger.info("消息状态:=="+sendResult.getSendStatus());
logger.info("======:"+SendStatus.SEND_OK);
if((sendResult == null) || (sendResult.getSendStatus() != SendStatus.SEND_OK)){
logger.info("=====消息发送失败:"+sendResult.getSendStatus());
return;
}
} catch (MQClientException e) {
e.printStackTrace();
logger.error("================MQ连接异常===================");
} catch (RemotingException e) {
e.printStackTrace();
} catch (MQBrokerException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
创建了一个DefaultMQProducer对象,同时设置了GroupName和NameServer地址,然后创建消息消息通过DefaultMQProducer将消息发送出去,返回一个SendResult对象;
五.消费者自动监听队列
@Component
public class RocketMQConsumer {
private final Log logger = LogFactory.getLog(getClass());
@Value("${rocketmq.namesrvAddr}")
private String namesrvAddr;
@Value("${rocketmq.consumerGroup}")
private String consumerGroup;
@Value("${rocketmq.topic}")
private String topic;
@Value("${rocketmq.topicTag}")
private String topicTag;
@Value("${rocketmq.consumeFromWhere}")
private String consumeFromWhere;
@Value("${rocketmq.messageModel}")
private String messageModel;
@Bean
public DefaultMQPushConsumer getRocketMQConsumer() throws MQClientException {
logger.info("======rocketmq start======");
DefaultMQPushConsumer defaultMQPushConsumer = new DefaultMQPushConsumer(consumerGroup);
defaultMQPushConsumer.setNamesrvAddr(namesrvAddr);
defaultMQPushConsumer.setInstanceName(String.valueOf(System.currentTimeMillis()));
if ("CONSUME_FROM_FIRST_OFFSET".equals(consumeFromWhere)) { //从头到尾消费
defaultMQPushConsumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
} else if ("CONSUME_FROM_LAST_OFFSET".equals(consumeFromWhere)) { //从尾部开始消费
defaultMQPushConsumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
} else if ("CONSUME_FROM_TIMESTAMP".equals(consumeFromWhere)) { //指定时间消费
defaultMQPushConsumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_TIMESTAMP);
} else {
defaultMQPushConsumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
}
// 订阅主题和 标签( * 代表所有标签)下信息
defaultMQPushConsumer.subscribe(topic, topicTag);
if (messageModel == null) {
defaultMQPushConsumer.setMessageModel(MessageModel.CLUSTERING);
}else if ("CLUSTERING".equals(messageModel)){ //集群模式
defaultMQPushConsumer.setMessageModel(MessageModel.CLUSTERING);
}else if ("BROADCASTING".equals(messageModel)){ //广播
defaultMQPushConsumer.setMessageModel(MessageModel.BROADCASTING);
}else {
defaultMQPushConsumer.setMessageModel(MessageModel.CLUSTERING);
}
//注册消费的监听 并在此监听中消费信息,并返回消费的状态信息
defaultMQPushConsumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
// msgs中只收集同一个topic,同一个tag,并且key相同的message
// 会把不同的消息分别放置到不同的队列中
try {
for (Message msg : msgs) {
// 消费者获取消息 这里只输出 不做后面逻辑处理
String body = new String(msg.getBody(), "utf-8");
logger.info("==========mq参数=========="+body);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
defaultMQPushConsumer.start();
logger.info("consumerGroup:" + consumerGroup + " namesrvAddr:" + namesrvAddr + " start success!");
return defaultMQPushConsumer;
}