SpringBoot 整合集成 RocketMq(一)

  • 前言

SpringBoot 是目前Java开发中的主流框架,RocketMQ 也是MQ里的佼佼者,这里做一个Sptring Boot 项目 整合集成 RocketMQ 的 Demo.

  • 环境准备 

    SpringBoot 项目

    RocketMq(安装流程 docker安装方式 https://my.oschina.net/u/4213839/blog/5064591 , 普通安装 https://my.oschina.net/u/4213839/blog/4965230 )

  • Coding

引入 RocketMq 的依赖

        <!-- RocketMQ -->
        <dependency>
            <groupId>com.alibaba.rocketmq</groupId>
            <artifactId>rocketmq-all</artifactId>
            <version>3.2.6</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>com.alibaba.rocketmq</groupId>
            <artifactId>rocketmq-client</artifactId>
            <version>3.2.6</version>
        </dependency>

首先定义一个这个Demo相关的常量类

package com.lsz.test.recketmq;

/**
 * 相关常量类
 *
 * @author lishuzhen
 * @date 2021/5/31 22:53
 */
public class MqConstant {

    public static final String NAME_SRV_ADDR = "192.168.109.128:9876";

    public static final String TEST_TOPIC = "TEST_TOPIC";

    public static final String CONSUMER_GROUP_1 = "CONSUMER_GROUP_1";

    public static final String PRODUCER_GROUP_1 = "PRODUCER_GROUP_1";
}

编写 消息的生产者

package com.lsz.test.recketmq;

import com.alibaba.rocketmq.client.exception.MQClientException;
import com.alibaba.rocketmq.client.producer.DefaultMQProducer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 消息生产者
 *
 * @author lishuzhen
 * @date 2021/5/31 21:54
 */
public class RocketMqProducer {
    private final Logger logger = LoggerFactory.getLogger(RocketMqProducer.class);

    private DefaultMQProducer defaultMQProducer;

    public void init() throws MQClientException {
        logger.info("RocketMqProducer initialize!");

        // 初始化
        defaultMQProducer = new DefaultMQProducer(MqConstant.PRODUCER_GROUP_1);
        defaultMQProducer.setNamesrvAddr(MqConstant.NAME_SRV_ADDR);
        defaultMQProducer.setInstanceName(String.valueOf(System.currentTimeMillis()));
        defaultMQProducer.start();

        logger.info("RocketMqProducer start success!");

    }

    public void destroy() {
        defaultMQProducer.shutdown();
    }

    public DefaultMQProducer getDefaultMQProducer() {
        return defaultMQProducer;
    }

}

编写 消息的消费者

package com.lsz.test.recketmq;

import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer;
import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere;
import com.alibaba.rocketmq.common.message.Message;
import com.alibaba.rocketmq.common.message.MessageExt;
import com.lsz.common.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * 消息消费者
 *
 * @author lishuzhen
 * @date 2021/5/31 22:58
 */
public class PushConsumer {
    private final Logger logger = LoggerFactory.getLogger(PushConsumer.class);
    private String myName;

    public PushConsumer(String myName) {
        this.myName = myName;
    }

    public void init() {
        logger.info("consumer running ... ");
        DefaultMQPushConsumer consumer =
                new DefaultMQPushConsumer(MqConstant.CONSUMER_GROUP_1);
        consumer.setNamesrvAddr(MqConstant.NAME_SRV_ADDR);
        try {
            // 订阅话题 并指定 tag
            consumer.subscribe(MqConstant.TEST_TOPIC, "tag1 || tag2");

            consumer.setConsumeFromWhere(
                    ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
            consumer.registerMessageListener(
                    new MessageListenerConcurrently() {
                        @Override
                        public ConsumeConcurrentlyStatus consumeMessage(
                                List<MessageExt> list,
                                ConsumeConcurrentlyContext Context) {
                            Message msg = list.get(0);
                            logger.info("mq {} time {}, 消息{}, 消息内容 = {}",
                                    myName, DateUtils.dateTimeNow(), msg, new String(msg.getBody()));
                            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                        }
                    }
            );
            consumer.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

定义一个生成bean的工厂类,只是为了做demo,初始化bean使用。

package com.kindergarten.test.recketmq;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * MQ 相关配置类
 *
 * @author lishuzhen
 * @date 2021/5/31 22:55
 */
@Configuration
public class MqBeanFactory {


    @Bean(initMethod = "init", destroyMethod = "destroy")
    public RocketMqProducer createRocketMqProducer() {
        return new RocketMqProducer();
    }


    @Bean(name = "Consumer1", initMethod = "init")
    public PushConsumer createPushConsumer1() {
        return new PushConsumer("Consumer1");
    }

    @Bean(name = "Consumer2", initMethod = "init")
    public PushConsumer createPushConsumer2() {
        return new PushConsumer("Consumer2");
    }
}

最后编写一个测试接口

package com.lsz.test.recketmq;

import com.alibaba.rocketmq.client.exception.MQBrokerException;
import com.alibaba.rocketmq.client.exception.MQClientException;
import com.alibaba.rocketmq.client.producer.SendResult;
import com.alibaba.rocketmq.client.producer.SendStatus;
import com.alibaba.rocketmq.common.message.Message;
import com.alibaba.rocketmq.remoting.exception.RemotingException;
import com.lsz.common.result.ResultVO;
import com.lsz.common.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author lishuzhen
 * @date 2021/5/31 22:56
 */
@RestController
@RequestMapping("api/mq")
public class MqController {
    private final Logger logger = LoggerFactory.getLogger(MqController.class);

    @Autowired
    private RocketMqProducer rocketMqProducer;


    /**
     * 发送消息
     *
     * @param str
     * @return
     */
    @GetMapping("sendMsg/{tags}/{str}/{count}")
    public ResultVO sendMsg(@PathVariable String str, @PathVariable String tags, @PathVariable Long count) {
        Long successCount = 0L;
        try {
            for (Long i = 0L; i < count; i++) {
                Message msg = new Message(MqConstant.TEST_TOPIC,
                        tags,
                        "HELLO_" + System.currentTimeMillis(),
                        (str + i).getBytes());
                logger.info("mq producer time {}, 消息{}, 消息内容 = {}",
                        DateUtils.dateTimeNow(), msg, new String(msg.getBody()));
                SendResult result = rocketMqProducer.getDefaultMQProducer().send(msg);
                logger.info("mq producer 回调 time {}, result= {} ",
                        DateUtils.dateTimeNow(), result);
                if (SendStatus.SEND_OK.equals(result.getSendStatus())) {
                    successCount++;
                }

            }

        } catch (MQClientException e) {
            e.printStackTrace();
        } catch (RemotingException e) {
            e.printStackTrace();
        } catch (MQBrokerException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return ResultVO.success(successCount);
    }
}

使用PostMan 调用接口 

up-cefda4c0fe800826903eb06f91edf3603d9.png

查看日志

23:09:37.517 [http-nio-8080-exec-5] INFO  c.k.t.r.MqController - [sendMsg,47] - mq producer time 20210531230937, 消息Message [topic=TEST_TOPIC, flag=0, properties={KEYS=HELLO_1622473777517, WAIT=true, TAGS=tag1}, body=8], 消息内容 = TestMsg0
23:09:37.532 [http-nio-8080-exec-5] INFO  c.k.t.r.MqController - [sendMsg,50] - mq producer 回调 time 20210531230937, result= SendResult [sendStatus=SEND_OK, msgId=C0A86D8000002A9F000000000000009A, messageQueue=MessageQueue [topic=TEST_TOPIC, brokerName=broker-a, queueId=1], queueOffset=0] 
23:09:37.533 [ConsumeMessageThread_2] INFO  c.k.t.r.PushConsumer - [consumeMessage,48] - mq Consumer1 time 20210531230937, 消息MessageExt [queueId=1, storeSize=154, queueOffset=0, sysFlag=0, bornTimestamp=1622473777518, bornHost=/192.168.109.1:49251, storeTimestamp=1622473776306, storeHost=/192.168.109.128:10911, msgId=C0A86D8000002A9F000000000000009A, commitLogOffset=154, bodyCRC=1602806610, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message [topic=TEST_TOPIC, flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=1, KEYS=HELLO_1622473777517, WAIT=true, TAGS=tag1}, body=8]], 消息内容 = TestMsg0

可以看到消息马上就被消费了,延迟很低。

在RocketMQ 控制台查看消息

up-d8db32ea8f3e7e4c0c7ac1ff190aee5f9f7.png

 

PS: 安装 RocketMQ 的 NameServer,Broker,Console  使用docker安装 (推荐) 可参考   https://my.oschina.net/u/4213839/blog/5064591, 普通安装 https://my.oschina.net/u/4213839/blog/4965230 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值