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;
}