Springboot integrates rocketmq consumer pull message mode

Springboot integrates rocketmq consumer pull message mode

1. Introduction to push-pull mode of rocketmq message queue:

  • Push mode (push): The message producer sends the message to the broker, and then the broker actively pushes the message to the consumer that has subscribed to the message.
  • Pull mode (pull): The message producer sends the message to the broker, and then the consumer spontaneously goes to the broker to pull the message.

Why use the consumer-side pull message consumption model:
We all know that the message middleware can publish or push messages to the consumer-side, if the request concurrency is not very high, and the processing capacity of the consumer module is not bad, There is nothing wrong with this push processing mode.
However, in the case of high concurrent requests, such a method of directly pushing messages to the consumer module is likely to cause the consumer module to crash or the program is stuck. At this time, you might as well try to use the consumer pull mode. (Pull) to achieve business message processing.

2. Case display The
case uses springboot project, java1.8 version, rocketmq4.3 version;
2.1 add pom dependency

        <!--rocket客户端依赖-->
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-client</artifactId>
            <version>4.3.0</version>
        </dependency>

2.2 Configure the producer

@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 Publish a message and pull the message on another interface to test the effect

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 Test the effect:
the dependency of swagger added in the module can be tested with postman: first call the message, then call the pull interface;
Insert picture description here
log display effect:

we can copy an encrypted message, and then decompile it: for example, the following The string
"body" in this body : "eyJpZCI6IjMiLCJ1c2VybmFtZSI6InlhbmdzaGlsZWkzIn0="
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_37488998/article/details/111468613