springboot整合rocketmq消费者拉取消息模式

springboot整合rocketmq消费者拉取消息模式

一、rocketmq消息队列的推拉模式介绍:

  • 推送模式(push):消息的生产者将消息发送到broker,然后broker将消息主动推送给订阅了该消息的消费者端。
  • 拉取模式(pull):消息生产者将消息发送到broker上,然后由消费者自发的去broker去拉取消息。

为什么要使用消费端拉取消息消费的模式:
我们都知道,消息中间件可以发布或者推送消息给消费者端,如果请求的并发不是很高,且消费者模块的处理能力还不错的情况下,这种推送处理的模式是没什么问题的。
但是,如果是高并发请求情况下,像这种直接将消息推送给消费端模块的方法很可能会导致消费端模块出现宕机或者程序卡死的问题,此时不妨尝试使用消费端拉取模式(pull)来实现业务消息处理。

二、案例展示
案例采用springboot项目,java1.8版本,rocketmq4.3版本;
2.1添加pom依赖

        <!--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中的字符串
“body”:“eyJpZCI6IjMiLCJ1c2VybmFtZSI6InlhbmdzaGlsZWkzIn0=”
在这里插入图片描述

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为了在SpringBoot项目中使用RocketMQ,我们需要添加相应的依赖和配置。下面是一个简单的配置示例: 1. 添加依赖: ```xml <dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-spring-boot-starter</artifactId> <version>{rocketmq.version}</version> </dependency> ``` 2. 配置属性: ```properties # name server地址,多个地址用逗号分隔 rocketmq.name-server=127.0.0.1:9876 # 生产者组名 rocketmq.producer.group=producer_group # 消费者组名 rocketmq.consumer.group=consumer_group # 配置消费者是否是广播模式,默认为集群模式 rocketmq.consumer.broadcasting=false # 消费者消息拉取间隔,默认为1秒 rocketmq.consumer.pull-interval=0 # 生产者发送消息超时时间,默认3秒 rocketmq.producer.send-timeout=3000 # 消费者消费消息超时时间,默认15分钟 rocketmq.consumer.consume-timeout=900000 # 消息最大长度,默认4MB rocketmq.producer.max-message-size=4194304 # 发送消息失败后重试次数,默认为2次 rocketmq.producer.retry-times-when-send-failed=2 # 消费者每次消费消息的最大数量,默认为1条 rocketmq.consumer.consume-message-batch-max-size=1 ``` 3. 定义生产者和消费者: ```java @Component public class MyProducer { @Autowired private RocketMQTemplate rocketMQTemplate; public void send(String topic, String message) { rocketMQTemplate.convertAndSend(topic, message); } } @Component public class MyConsumer implements RocketMQListener<String> { @Override public void onMessage(String message) { System.out.printf("Received message: %s\n", message); } } ``` 在这个示例中,我们定义了一个生产者和一个消费者。生产者使用RocketMQTemplate发送消息消费者实现RocketMQListener接口来处理消息

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值