【中间件_RocketMQ_01】Spring Boot 集成 RocketMQ 实现简单的消息发送和消费

本文主要有以下内容:

  • 简单消息的发送
  • 顺序消息的发送
  • RocketMQTemplate的API介绍

环境搭建:

RocketMQ的安装教程:在官网上下载bin文件,解压到本地,并配置环境变量,如下图所示:

在 Spring boot 项目中引入 RocketMQ 依赖:

xml 复制代码
<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-spring-boot-starter</artifactId>
    <version>2.2.3</version>
</dependency>

在application.yml增加相关配置:

yml 复制代码
server:
  port: 10001
rocketmq:
  name-server: 127.0.0.1:9876
  producer:
    group: springboot_produce_group # 必须指定group
    send-message-timeout: 3000 # 消息发送超时时长,默认3s
    retry-times-when-send-failed: 3 # 同步发送消息失败重试次数,默认2
    retry-times-when-send-async-failed: 3 # 异步发送消息失败重试次数,默认2
  consumer:
    group: springboot_consumer_group

在 Spring Boot 中使用RocketMQ很简单直接注入RocketMQTemplate对象即可:

java 复制代码
@Resource
private RocketMQTemplate rocketMQTemplate;

基本概念

消息和主题相关:

消息 message:通信交互的载体,分为事务消息,半事务消息,延迟消息,顺序消息等。

主题 topic:一类消息的集合,逻辑概念。

队列 queue:主题由一个队列或者多个队列构成,当消息发送到某一个主题时,需要选择某一个队列。

偏移量 offset:消息追加到主题的队列后会分配一个数值,表示该队列的几条消息。

消费者相关:

消费组 consume group:消费组用于订阅主题消费消息,可以订阅多个主题,一个消费组可以有多个消费者。

广播模式:同一个消费组内的所有消费者都会消费订阅主题的所有消息。即一条消息会被该消费者组的所有消费者消费。

集群模式:同一个消费组内的所有消费者只消费订阅主题的一部分消息,即一条消息只会被改消费组的一个消费者消费。

并发消费:同一个队列的消息由多线程消费且不保证消息的顺序。

顺序消费:保证同一队列的消息按顺序消费。

发送普通消息

创建MsgController,代码如下:

java 复制代码
@RestController
@RequestMapping("send/")
@CrossOrigin(allowedHeaders = "*", origins = "*")
@Slf4j
public class MsgController {
    @Resource
    private RocketMQTemplate rocketMQTemplate;
    @GetMapping("normal")
    public void sendNormalMsg() {
        Message<String> msg = MessageBuilder.withPayload("Hello,RocketMQ Normal_msg").build();
        rocketMQTemplate.send("normal_msg", msg);
    }
}

创建消息的消费者,只需要实现RocketMQListener接口中的方法即可,代码如下:

java 复制代码
@Component
@RocketMQMessageListener(topic = "normal_msg", consumerGroup = "consumer_normal")
@Slf4j
public class NormalMsgConsumer implements RocketMQListener<String> {
    @Override
    public void onMessage(String message) {
        log.info("Receive Normal Msg: {}",message);
    }
}

@RocketMQMessageListener注解用在消费者类上,指定当前类消费的主题。

  • topic:指定消费者的主题
  • comsumerGroup:指定消费者组(Consumer Group)名称,用于区分不同的消费者。

启动项目,运行结果如下图所示:

发送顺序消息

顺序消息:保证同一队列的消息按顺序消费。

在MsgController 中添加如下代码:

java 复制代码
@GetMapping("order")
public void sendOrderMsg(){
​
    log.info("开始发送顺序消息");
    for (int j = 0; j < 10; j++) {
        Message<String> sendOrderMsg = MessageBuilder.withPayload("Send Order Msg = " + j + " time: "+ LocalDateTime.now()).build();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        rocketMQTemplate.convertAndSend("msg:order", sendOrderMsg);
    }
    log.info("顺序消息发送结束");
}

创建对应topic消息的消费者,代码如下所示:

java 复制代码
@Component
@RocketMQMessageListener(topic = "msg",
        consumerGroup = "consumer_order_group",
        selectorExpression = "order",
        messageModel = MessageModel.CLUSTERING,
        selectorType = SelectorType.TAG)
@Slf4j
public class OrderMsgConsumer implements RocketMQListener<String> {
    @Override
    public void onMessage(String message) {
        log.info("Receive Order Msg: {}",message);
    }
}

@RocketMQMessageListener其他属性介绍:

  • selectorExpression: 消息选择表达式,用于过滤消息,只有满足表达式条件的消息才会被消费。默认值为 *,表示订阅所有消息。

    • 全匹配:*,默认值。
    • 属性匹配:指定tag = 'tagName',上面的代码就可以改写为"tag = 'order'"
    • 表达式匹配:需要指定selectType = SelectorType.SQL92,见下面。
  • selectorType:指明了消息选择通过tag的方式,默认值SelectorType.TAG。可选值有SelectorType.SQL92

    • TAG:支持"tagName"的方式配置,如果有多个标签则用||进行连接
    • SQL92:关键字有AND, OR, NOT, BETWEEN, IN, TRUE, FALSE, IS, NULL。支持的数据类型有Boolean, String, Decimal, Float number等。使用方式如(a > 10 AND a < 100) OR (b IS NOT NULL AND b=TRUE)
  • messageModel:消息模式,可选值为 MessageModel.CLUSTERING(默认)或 MessageModel.BROADCASTING,分别表示集群模式和广播模式。

重新启动项目,运行结果如下图所示:

RocketMQTemplate的API介绍

在上面的api使用中,都没有去关注是否消息发送的状态,如是否成功,发送到了哪一个队列等。接下来就介绍一下相关API的使用

  • 带返回值的发送普通消息 SendResult syncSend(String destination, Message<?> message);

在MsgController添加如下代码:

java 复制代码
@GetMapping("normal_result")
public void sendNormalResultMsg() {
    Message<String> msg = MessageBuilder.withPayload("normal_return_result").build();
    SendResult normalMsg = rocketMQTemplate.syncSend("normal_msg", msg);
    log.info("normalMsg = {}",normalMsg);
}

如log所示,可以看到发送状态等信息。

  • 发送异步消息 ,在MsgController中添加如下代码:
java 复制代码
@GetMapping("callback")
public void sendNormalResultMsgWithCallback(){
    Message<String> msg = MessageBuilder.withPayload("normal_return_result").build();
    rocketMQTemplate.asyncSend("normal_msg", msg, new SendCallback() {
        @Override
        public void onSuccess(SendResult sendResult) {
            log.info("success");
        }
        @Override
        public void onException(Throwable throwable) {
            log.info("error");
        }
    });
}

运行结果如下所示:

  • 发送顺序消息:在第二部分以及展示过了也可以用如下代码替换
java 复制代码
rocketMQTemplate.convertAndSend("msg:order", sendOrderMsg);
// 替换为
rocketMQTemplate.syncSendOrderly("msg:order", sendOrderMsg,String.valueOf(j));
  • 发送单向消息
java 复制代码
@GetMapping("oneway")
public void  sendOneWay(){
    Message<String> oneWay = MessageBuilder.withPayload("Send Order Msg = " + " time: "+ LocalDateTime.now()).build();
    rocketMQTemplate.sendOneWay("normal_msg",oneWay);
}

运行结果如下图所示:

  • 发送事务消息:暂不举例,后续补充
  • 发送事务消息带回调:和syncSend()类似,后续补充相关用法。

参考资料:

  • 《RocketMQ 实战》
相关推荐
哦虎!3 小时前
【JavaEE】网络初识
java
for_ever_love__3 小时前
MySQL ORDER BY 排序优化:从 Using filesort 到索引有序扫描(含双路 / 单路排序原理)
java·mysql·优化·存储·by·order·filesort
大鸡腿同学3 小时前
手心向上,手心向下
后端
我是人✓4 小时前
Java文件上传三方式对比:从传统到SpringBoot
java·开发语言
欣栀♡4 小时前
JVM 频繁 Full GC 先看日志括号里的 cause,jstat 的 FGC 在 JDK 8 上会骗人
java·jvm
CCblandy4 小时前
令牌桶在 0.9 倍负载超发 19%、固定窗口边界放行 20 个:四种限流算法同构实测
后端·python·算法·性能优化·架构
IT研究室4 小时前
最新计算机毕业设计选题推荐-基于spring boot的葡萄酒文化宣传网站-网站-文档指导-Java-springboot
java·spring boot·课程设计
慧都小项4 小时前
MyEclipse 中创建和测试 JAX-RS REST 接口:从项目配置到 REST Explorer
java·restful·myeclipse·jax-rs
Wang's Blog4 小时前
Java 项目实战: 交友项目 - 入门案例:编写 Dubbo 服务提供者
java·dubbo·交友
秋饼5 小时前
Spring AI 2.0 结构化输出企业级实战:从 BeanOutputConverter 源码到生产级解析容错
java·ai·技术分享·后端开发