RocketMQ快速入门整合SpringBoot

最近接触到的一个项目有用到RocketMQ需要整合SpringBoot,因为之前没有用过(只是用RabbitMQ),所有特地学习记录一下。本文主要是对RocketMQ做简单介绍(一些基本概念),以及对SpringBoot的整合还有整合过程中遇到的一些问题做一个记录。

一、RocketMQ介绍及基本概念

1.1介绍

RocketMQ 是阿里巴巴开源的队列模型的消息中间件,具有高性能、高可靠、高实时、分布式特点。我们需要先对他的一些基本概念有所了解,即Producer、Consumer、Broker、NameServer、Group、Topic等。

1.2基本概念

RocketMQ主要由 Producer、Broker、Consumer 三部分组成,其中Producer 负责生产消息,Consumer 负责消费消息,Broker 负责存储消息。Broker 在实际部署过程中对应一台服务器,每个 Broker 可以存储多个Topic的消息,每个Topic的消息也可以分片存储于不同的 Broker。Message Queue 用于存储消息的物理地址,每个Topic中的消息地址存储于多个 Message Queue 中。ConsumerGroup 由多个Consumer 实例构成。

1.Name Server:名称服务充当路由消息的提供者。是一个几乎无状态节点,可集群部署,节点之间无任何信息同步。在消息队列 RocketMQ 中提供命名服务,更新和发现 Broker 服务。

2.Broker:消息中转角色,负责存储消息,转发消息。可以理解为消息队列服务器,提供了消息的接收、存储、拉取和转发服务。broker是RocketMQ的核心,它不不能挂的,所以需要保证broker的高可用。

3.Producer:Producer表示消息队列的生产者。消息队列的本质就是实现了publish-subscribe模式,生产者生产消息,消费者消费消息。所以这里的Producer就是用来生产和发送消息的,一般指业务系统。

4.Consumer:消息消费者,一般由业务后台系统异步的消费消息。

5.Group:又有Produser Group和Consumer Group可以看做是一类生产者和消费者的集合。

6.Topic:代表普通的消息队列,而Queue是组成Topic的更小单元(可以看成是Queue的集合)。
以上是一些RocketMQ的基本概念,详细的可以参考:https://www.cnblogs.com/weifeng1463/p/12889300.html

二、RocketMQ整合SpringBoot

在整合之前我们需要先下载RocketMQ,本文直接是在本地使用(学习及调试更方便),下载地址(https://github.com/apache/rocketmq/tags),为了方便我们也下载RocketMQ图形界面
RocketMQ快速入门整合SpringBoot_第1张图片
下载解压完启动RocketMQ
RocketMQ快速入门整合SpringBoot_第2张图片

#cmd启动,先启动mqnamesrv后启动mqbroker
start mqnamesrv.cmd
start mqbroker.cmd -n 127.0.0.1:9876 autoCreateTopicEnable=true

如果在启动Broker过程中报找不到主加载类的错,可以如下编辑runbroker.cmd添加引号(RocketMQ需要依赖java环境)
在这里插入图片描述
另外我们可以将下载的图形工具打包运行(需要修改配置文件指定RocketMQ地址)可以让我们学习的时候更直观。

mvn clean package -Dmaven.test.skip=true #打包
java -jar rocketmq-console-ng-1.0.0.jar #运行

以上完成准备操作。

2.1整合方式一

分别创建producer服务和consumer服务
1.分别引入RocketMQ的依赖

<dependency>
	<groupId>com.alibaba.rocketmqgroupId>
	<artifactId>rocketmq-clientartifactId>
	<version>3.2.6version>
dependency>

2.producer服务编写生产者

	@RequestMapping("/hi/{id}")
    public Response sayHi(@PathVariable Integer id){
        DefaultMQProducer defaultMQProducer = new DefaultMQProducer();
        try {
            defaultMQProducer.setProducerGroup("my-producer-group");
            defaultMQProducer.setNamesrvAddr("127.0.0.1:9876");
            defaultMQProducer.setInstanceName("producer01");
            defaultMQProducer.start();
            String msg="这个是使用单独的rocketmq发送的消息-"+id;
            Message message = new Message("first-topic",msg.getBytes());
            SendResult send = defaultMQProducer.send(message);
            log.info("----------------发送消息返回的结果:{}",send);
            defaultMQProducer.shutdown();
            return Response.ok();
        }catch (Exception e){
            log.error(e.getMessage());
            log.info("发送失败");
        }
        return Response.fail();
    }

3.consumer服务编写消费者

@Slf4j
@Configuration
public class RocketMQConfig {

    @Bean("consumer001")
    public DefaultMQPushConsumer consumer01() throws Exception{
        DefaultMQPushConsumer defaultMQPushConsumer = new DefaultMQPushConsumer();
        defaultMQPushConsumer.setInstanceName("first-consumer");
        defaultMQPushConsumer.setNamesrvAddr("127.0.0.1:9876");
        defaultMQPushConsumer.setConsumerGroup("my-producer-group");
        defaultMQPushConsumer.subscribe("first-topic","*");
        defaultMQPushConsumer.registerMessageListener(new Consumer01());
        defaultMQPushConsumer.start();
        return defaultMQPushConsumer;
    }

    @Bean("consumer002")
    public DefaultMQPushConsumer consumer02() throws Exception{
        DefaultMQPushConsumer defaultMQPushConsumer = new DefaultMQPushConsumer();
        defaultMQPushConsumer.setInstanceName("second-consumer");
        defaultMQPushConsumer.setNamesrvAddr("127.0.0.1:9876");
        defaultMQPushConsumer.setConsumerGroup("my-producer-group");
        defaultMQPushConsumer.subscribe("first-topic","*");
        defaultMQPushConsumer.registerMessageListener(new Consumer02());
        defaultMQPushConsumer.start();
        return defaultMQPushConsumer;
    }
}
@Slf4j
@Component
public class Consumer01 implements MessageListenerConcurrently {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
        for (MessageExt msg:list){
            String result="";
            try {
                result = new String(msg.getBody(), "utf-8");
                log.info("=====consumer01 消费结果:{}",result);
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }catch (Exception e){
                log.error(e.getMessage());
                log.info("消费失败");
            }
        }
        return ConsumeConcurrentlyStatus.RECONSUME_LATER;
    }
}

启动服务进行测试,刚开始没有为每个消费者分别设置实例名称,结果导致报错(The consumer group[my-producer-group] has been created before, specify another name please),后来调用setInstanceName为每个消费者分别设置实例名称就好了。

2.2整合方式二

创建producer服务和consumer服务
1.分别引入RocketMQ依赖

<dependency>
	<groupId>org.apache.rocketmqgroupId>
	<artifactId>rocketmq-spring-boot-starterartifactId>
	<version>2.1.0version>
dependency>

2.配置yml文件producer服务编写生产者
RocketMQ快速入门整合SpringBoot_第3张图片

@Slf4j
@RestController
public class HelloRocketMQ {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    //使用mq-starter的形式发送消息
    @RequestMapping("/hello/{i}")
    public Response hello(@PathVariable Integer i){
        try {
            String message="这是第一条消息"+i;
            rocketMQTemplate.convertAndSend("first-topic",message);
            System.out.println("生产:"+message);
            return Response.ok();
        }catch (Exception e){
            log.info("信息发送失败了!!!!",e);
        }
        return Response.fail();
    }
}

3.配置yml文件consumer服务编写消费者
在这里插入图片描述

@Component
/**
 * @RocketMQMessageListener注解指定消费组和topic
 */
@RocketMQMessageListener(topic = "first-topic",consumerGroup = "my-producer-group")
public class HelloConsumer implements RocketMQListener<String> {
    @Override
    public void onMessage(String s) {
        System.out.println("消费者1:"+s);
    }
}
//@RocketMQMessageListener注解指定消费组和topic
@Component
@RocketMQMessageListener(topic = "first-topic",consumerGroup = "my-producer-group")
public class HelloConsumer2 implements RocketMQListener<String>, RocketMQPushConsumerLifecycleListener {
    @Override
    public void onMessage(String s) {
        System.out.println("消费者2:"+s);
    }

	//解决多个消费者消费同一消费组同一个topic报错问题
    @Override
    public void prepareStart(DefaultMQPushConsumer defaultMQPushConsumer) {
        defaultMQPushConsumer.setInstanceName("consumer2");
    }
}

启动producer服务和consumer服务测试,上面的(The consumer group[my-producer-group] has been created before, specify another name please)问题我们可以通过实现RocketMQPushConsumerLifecycleListener 来为每个消费者设置实例名称。

你可能感兴趣的:(MQ,后端,中间件,java)