Springbootはrocketmqコンシューマプルメッセージモードを統合します
1. rocketmqメッセージキューのプッシュプルモードの概要:
- プッシュモード(プッシュ):メッセージプロデューサーはメッセージをブローカーに送信し、ブローカーはメッセージをサブスクライブしたコンシューマーにメッセージをアクティブにプッシュします。
- プルモード(プル):メッセージプロデューサーはメッセージをブローカーに送信し、次にコンシューマーは自発的にブローカーに移動してメッセージをプルします。
コンシューマー側のプルメッセージ消費モデルを使用する理由:
要求の同時実行性がそれほど高くなく、コンシューマーモジュールの処理能力が悪くない場合、メッセージミドルウェアがメッセージをコンシューマー側に公開またはプッシュできることは誰もが知っています。このプッシュ処理モードに問題はありません。
ただし、同時リクエスト数が多い場合、メッセージをコンシューマーモジュールに直接プッシュするこのような方法では、コンシューマーモジュールがクラッシュしたり、プログラムがスタックしたりする可能性があります。現時点では、コンシューマープルを使用することをお勧めします。モード。(プル)ビジネスメッセージ処理を実現します。
2.ケースの表示
ケースはspringbootプロジェクト、java1.8バージョン、rocketmq4.3バージョンを使用し、2.1pom
依存関係を追加します
<!--rocket客户端依赖-->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.3.0</version>
</dependency>
2.2プロデューサーを構成する
@Configuration
@Slf4j
public class RocketMQConfiguration {
/**
* 创建支持消息事务发送的实例
* @return
* @throws MQClientException
*/
@Bean
public DefaultMQProducer transactionProducer()throws MQClientException{
TransactionMQProducer producer = new TransactionMQProducer("user_group");
producer.setInstanceName("user_producer_instance");
producer.setNamesrvAddr("localhost:9876");
producer.setRetryTimesWhenSendAsyncFailed(10);
producer.start();
log.info("支持事务消息的实例创建完成....");
return producer;
}
}
2.3メッセージを公開し、別のインターフェイスでメッセージをプルして効果をテストします
package com.demo.rocketmq.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.demo.rocketmq.dto.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.DefaultMQPullConsumer;
import org.apache.rocketmq.client.consumer.PullResult;
import org.apache.rocketmq.client.consumer.PullStatus;
import org.apache.rocketmq.client.producer.*;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Set;
@Slf4j
@RestController
@Api
public class ProducerController {
@Autowired
private DefaultMQProducer defaultProducer;
@Autowired
private TransactionMQProducer transactionProducer;
/**
* 发送普通消息
*/
@GetMapping("/sendMessage")
@ApiOperation(value = "发送普通消息", notes = "发送普通消息")
public void sendMsg() {
log.info("进入发送普通消息方法,发送5个用户==={}",defaultProducer.toString());
User user = new User();
for(int i=0;i<5;i++){
user.setId(String.valueOf(i));
user.setUsername("yangshilei"+i);
String json = JSON.toJSONString(user);
Message msg = new Message("user-topic","white",json.getBytes());
try {
SendResult result = defaultProducer.send(msg);
log.info("发送次数{}:消息id={}:发送状态={}",i,result.getMsgId(),result.getSendStatus());
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 测试消费者拉取消息,本样例中只拉取了几条消息,并将拉取到的消息日志写出来。
*/
@ApiOperation(value = "测试消费者拉取消息", notes = "测试消费者拉取消息")
@GetMapping("/test/getmessage")
public void testConsumer() throws Exception {
DefaultMQPullConsumer consumer = new DefaultMQPullConsumer("user_consumer_group");
consumer.setNamesrvAddr("127.0.0.1:9876");
consumer.setInstanceName("user_consumer_instance");
consumer.start();
System.out.println("消费者创建完成");
Set<MessageQueue> messageQueues = consumer.fetchSubscribeMessageQueues("user-topic");
System.out.println("拉取到的队列数量"+messageQueues.size());
for(MessageQueue queue : messageQueues){
System.out.println("遍历队列queue"+queue);
long offset = consumer.fetchConsumeOffset(queue, true);
System.out.println("consumer from the queue:" + queue + ":" + offset);
for(int i = 0; i < 10;i++){
// 在队列中拉取不到消息会一直阻塞等待着,直到能拉取到消息
// PullResult pullResult = consumer.pullBlockIfNotFound(queue, null, consumer.fetchConsumeOffset(queue, false), 1);
// 在队列中拉取不到消息就结束
PullResult pullResult = consumer.pull(queue, null, consumer.fetchConsumeOffset(queue, false), 1);
consumer.updateConsumeOffset(queue,pullResult.getNextBeginOffset());
switch (pullResult.getPullStatus()){
case FOUND:
List<MessageExt> messageExtList = pullResult.getMsgFoundList();
for (MessageExt m : messageExtList) {
System.out.println("拉取到数据===="+JSONObject.toJSONString(m));
}
break;
case NO_MATCHED_MSG:
break;
case NO_NEW_MSG:
break;
case OFFSET_ILLEGAL:
break;
default:
break;
}
}
}
System.out.println("关闭消费者");
consumer.shutdown();
}
}
2.4効果のテスト:
モジュールに追加されたswaggerの依存関係は、postmanでテストできます:最初にメッセージを呼び出し、次にプルインターフェイスを呼び出します;
ログ表示効果:
暗号化されたメッセージをコピーしてから逆コンパイルできます:たとえば、次の文字列
"body"この本文: "eyJpZCI6IjMiLCJ1c2VybmFtZSI6InlhbmdzaGlsZWkzIn0 ="