Springbootはrocketmqコンシューマプルメッセージモードを統合します

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 ="
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/qq_37488998/article/details/111468613