SpringCloud Alibaba】(十三)学习 RocketMQ 消息队列

目录

  • [1、MQ 使用场景与选型对比](#1、MQ 使用场景与选型对比)
    • [1.1、MQ 的使用场景](#1.1、MQ 的使用场景)
    • [1.2、引入 MQ 后的注意事项](#1.2、引入 MQ 后的注意事项)
    • [1.3、MQ 选型对比](#1.3、MQ 选型对比)
  • [2、下载、安装 RocketMQ 及 RocketMQ 控制台](#2、下载、安装 RocketMQ 及 RocketMQ 控制台)
    • [2.1、下载安装 RocketMQ](#2.1、下载安装 RocketMQ)
    • [2.2、测试 RocketMQ 环境](#2.2、测试 RocketMQ 环境)
    • [2.3、RocketMQ 控制台【图形化管理控制台】](#2.3、RocketMQ 控制台【图形化管理控制台】)
  • [3、RocketMQ 快速入门](#3、RocketMQ 快速入门)
  • [4、集成 RocketMQ](#4、集成 RocketMQ)
    • [4.1、用户微服务集成 RocketMQ](#4.1、用户微服务集成 RocketMQ)
    • [4.2、订单微服务整合 RocketMQ](#4.2、订单微服务整合 RocketMQ)
    • [4.3、测试集成的 RocketMQ](#4.3、测试集成的 RocketMQ)

1、MQ 使用场景与选型对比

1.1、MQ 的使用场景

MQ 的英文全称是 Message Queue,翻译成中文就是消息队列,队列实现了先进先出(FIFO)的消息模型。通过消息队列,我们可以实现多个进程之间的通信,例如,可以实现多个微服务之间的消息通信。MQ 的最简模型就是生产者生产消息,将消息发送到 MQ,消息消费者订阅 MQ,消费消息

MQ的使用场景通常包含:异步解耦、流量削峰

1.2、引入 MQ 后的注意事项

引入MQ最大的优点就是异步解耦和流量削峰,但是引入 MQ 后也有很多需要注意的事项和问题,主要包括:系统的整体可用性降低、系统的复杂度变高、引入了消息一致性的问题

  • 系统的整体可用性降低:在对一个系统进行架构设计时,引入的外部依赖越多,系统的稳定性和可用性就会降低。系统中引入了MQ,部分业务就会出现强依赖MQ的现象,此时,如果MQ宕机,则部分业务就会变得不可用。所以,引入MQ时,我们就要考虑如何实现MQ的高可用。
  • 系统的复杂度变高:引入 MQ 后,会使之前的同步接口调用变成通过 MQ 的异步调用,在实际的开发过程中,异步调用会比同步调用复杂的多。并且异步调用出现问题后,重现问题,定位问题和解决问题都会比同步调用复杂的多。并且引入 MQ 后,还要考虑如何保证消息的顺序等问题
  • 消息一致性问题 :引入 MQ 后,不得不考虑的一个问题就是消息的一致性问题。这期间就要考虑如何保证消息不丢失,消息幂等和消息数据处理的幂等性问题

1.3、MQ 选型对比

目前,在行业内使用的比较多的 MQ 包含 RabbitMQ、Kafka 和 RocketMQ。这里,我将三者的对比简单整理了个表格,如下所示:

消息中间件(MQ) 优点 缺点 使用场景
RabbitMQ 功能全面、消息的可靠性比较高 吞吐量低,消息大量积累会影响性能,使用的开发语言是 erlang,不好定制功能 规模不大的场景
Kafka 吞吐量最高,性能最好,集群模式下高可用 功能上比较单一,会丢失部分数据 日志分析,大数据场景
RocketMQ 吞吐量高,性能高,可用性高,功能全面。使用 Java 语言开发,容易定制功能 开源版不如阿里云上版文档比较简单 几乎支持所有场景,包含大数据场景和业务场景

2、下载、安装 RocketMQ 及 RocketMQ 控制台

2.1、下载安装 RocketMQ

Apache RocketMQ开发者指南

Windows 部署 RocketMQ

RocketMQ 下载、安装过程:

  1. 下载、解压。下载地址:二进制版本 4.9.2 官方下载

修改配置文件 conf/broker.conf

conf 复制代码
brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH

# 自动创建Topic
autoCreateTopicEnable=true
# nameServ地址
namesrvAddr=127.0.0.1:9876
# 存储路径
storePathRootDir=D:/dev/rocketmq-4.9.2/data/dataDir
# commitLog路径
storePathCommitLog=D:/dev/rocketmq-4.9.2/data/dataDir/commitlog
# 消息队列存储路径
storePathConsumeQueue=D:/dev/rocketmq-4.9.2/data/dataDir/consumequeue
# 消息索引存储路径
storePathIndex=D:/dev/rocketmq-4.9.2/data/dataDir/index
# checkpoint文件路径
storeCheckpoint=D:/dev/rocketmq-4.9.2/data/dataDir/checkpoint
# abort文件存储路径
abortFile=D:/dev/rocketmq-4.9.2/data/dataDir/abort
  1. 配置 ROCKETMQ 环境变量:否则,启动报错

    • 先添加一个环境变量 ROCKETMQ_HOME
    • 在 Path 中进行添加
  1. 内存分配设置【可选】

①:编辑 server 启动文件:bin/runserver.cmd

shell 复制代码
set "JAVA_OPT=%JAVA_OPT% -server -Xms256m -Xmx512m -Xmn512m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"

②:编辑 broker 启动文件:bin/runbroker.cmd

shell 复制代码
set "JAVA_OPT=%JAVA_OPT% -server -Xms256m -Xmx256m -Xmn128m"
  1. 修改日志存储默认路径:conf/logback_broker.xmlconf/logback_namesrv.xmlconf/logback_tools.xml
  1. 启动 NameServer

命令行执行:

shell 复制代码
mqnamesrv.cmd

打印出如下信息,说明 RocketMQ 的 NameServer 启动成功了:

  1. 启动 Broker

命令行执行:

shell 复制代码
mqbroker.cmd -n localhost:9876

打印出如下信息,说明 RocketMQ 的 Broker 服务启动成功了:

2.2、测试 RocketMQ 环境

RocketMQ 内置了大量的测试案例,并且这些测试案例可以通过 RocketMQ 的 bin 目录下的 tools.cmd 命令进行测试

1、启动生产者程序向 RocketMQ 发送消息

重新打开 cmd 命令行,进入 RocketMQ 的 bin 目录,在命令行输入如下命令调用 RocketMQ 自带的生产者程序向 RocketMQ 发送消息:

shell 复制代码
set NAMESRV_ADDR=localhost:9876
tools.cmd org.apache.rocketmq.example.quickstart.Producer

可以看到,执行完上述两条命令后,生产者程序开始向 RocketMQ 发送消息:

2、启动消费者程序消费 RocketMQ 中的消息

重新打开 cmd 命令行,进入 RocketMQ 的 bin 目录,在命令行输入如下命令调用 RocketMQ 自带的消费者程序消费 RocketMQ 中的消息

shell 复制代码
set NAMESRV_ADDR=localhost:9876
tools.cmd org.apache.rocketmq.example.quickstart.Consumer

可以看到,执行完上述两条命令后,消费者程序开始消费 RocketMQ 中的消息:

2.3、RocketMQ 控制台【图形化管理控制台】

2.3.1、下载、安装

RocketMQ 控制台本质上是一个 SpringBoot 程序,启动后默认监听的端口是 8080。RocketMQ 的新版控制台已经从 RocketMQ 的 rocketmq-externals 项目中分离出来了。也就是说,新版的 RocketMQ 控制台已经从 https://github.com/apache/rocketmq-externals 链接所示的项目中分离出来,新版控制台的链接地址为:https://github.com/apache/rocketmq-dashboard

1、下载 RocketMQ 控制台源码

2、修改配置:src/main/resources/application.properties

  • 端口:7000
  • namesrvAddr:localhost:9876
  • dataPath:D:/dev/rocket-mq-master/data

3、打开 cmd 命令行,进入 RocketMQ 控制台源码的根目录,输入如下 Maven 命令开始编 RocketMQ 控制台的源码:

shell 复制代码
mvn clean install -Dmaven.test.skip=true

4、编译完成后,会在 RocketMQ 控制台源码的根目录下生成 target 目录,进入 target 目录,可以看到生成了 rocketmq-dashboard-1.0.1-SNAPSHOT.jar 文件,如下所示

5、重新打开 cmd 命令行,进入 rocketmq-dashboard-1.0.0.jar 文件所在的目录,在命令行直接输入如下命令启动 RocketMQ 控制台程序

shell 复制代码
java -jar rocketmq-console-ng-1.0.0.jar

2.3.2、验证 RocketMQ 控制台

在浏览器中输入 http://localhost:7000 后,出现如下画面说明 RocketMQ 启动成功【可切换语言】:

选择【Topic】菜单想后可以看到目前 RocketMQ 中存在一个名称为 TopicTest 的主题:

点击 TopicTest 主题的状态按钮,如下所示:

可以看到,正确显示出了 TopicTest 主题的消息队列信息,说明 RocketMQ 控制台启动成功了

3、RocketMQ 快速入门

3.1、导入 RocketMQ 依赖

在用户微服务 shop-userpom.xml 中,添加 RocketMQ 相关的依赖,如下所示:

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

3.2、编写生产者代码

在用户微服务的 src/test/java 目录下新建 com.zzc.rocketmq.test包,在包下创建 RocketMQProducer 类,作为 RocketMQ 的生产者,代码如下所示:

java 复制代码
public class RocketMQProducer {
    public static void main(String[] args) throws Exception {
        // 1.创建消息生产者producer,并制定生产者组名
        DefaultMQProducer producer = new DefaultMQProducer("producerGroup");
        // 2.指定Nameserver地址
        producer.setNamesrvAddr("127.0.0.1:9876");
        // 3.启动producer
        producer.start();
        // 4.构建消息对象
        Message message = new Message("bingheTopic", "bingheTag", "Hello RocketMQ".getBytes());
        System.out.println("生产者发出的消息为:" + JSONObject.toJSONString(message));
        // 5.发送消息并接收结果
        SendResult sendResult = producer.send(message);
        System.out.println("生产者收到的发送结果信息为:" + JSONObject.toJSONString(sendResult));
        // 6.关闭生产者
        producer.shutdown();
    }
}

3.3、编写消费者代码

com.zzc.rocketmq.test 包下新建 RocketMQConsumer 类,作为 RocketMQ 的消费者,代码如下所示:

java 复制代码
public class RocketMQConsumer {
    public static void main(String[] args) throws Exception {
        // 1.创建消息消费者 consumer
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumerGroup");
        // 2.指定Nameserver地址
        consumer.setNamesrvAddr("127.0.0.1:9876");
        // 3.订阅 testTopic主题
        consumer.subscribe("testTopic", "*");
        // 4.设置消息监听,当收到消息时 RocketMQ 会回调消息监听
        consumer.registerMessageListener(new MessageListenerConcurrently() {
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
                // 打印消息消费者收到的RocketMQ消息
                System.out.println("消费者收到的消息为:" + list);
                // 返回消息消费成功的标识
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        // 5.启动消费者
        System.out.println("消费者启动成功");
        consumer.start();
    }
}

3.4、测试消息的生产与消费

1、为了便于观察,这里我们先启动消费者程序 RocketMQConsumer,启动 RocketMQConsumer后会在 IDEA 的控制台打印如下信息:

2、运行生产者程序 RocketMQProducer,运行后 RocketMQProducer 程序控制台会输出如下信息:

说明生产者程序 RocketMQProducer 成功将消息发送到 RocketMQ

3、接下来,再看下消费者程序 RocketMQConsumer 的控制台,如下所示:

说明生产者发送到 RocketMQ 的消息,被消费者成功消费到了

4、集成 RocketMQ

在项目中模拟一个用户成功下单后,为用户发送通知,通知用户下单成功的逻辑。

具体的流程:

下单成功后将订单的信息发送到 RocketMQ,然后用户微服务订阅 RocketMQ 的消息,接收到消息后进行打印

  • 用户微服务:消费者
  • 订单微服务:生产者

4.1、用户微服务集成 RocketMQ

1、在用户微服务 shop-user 导入了 RocketMQ 的依赖

2、在用户微服务 shop-userapplication.yml 文件中添加如下 RocketMQ 的配置

yml 复制代码
rocketmq:
  name-server: 127.0.0.1:9876

3、在用户微服务 shop-user 中创建 com.zzc.user.mq 包,在包下创建 RocketConsumeListener,实现 org.apache.rocketmq.spring.core.RocketMQListener 接口,具体代码如下所示:

java 复制代码
@Slf4j
@Component
@RocketMQMessageListener(consumerGroup = "user-group", topic = "order-topic")
public class RocketConsumeListener implements RocketMQListener<Order> {

    @Override
    public void onMessage(Order order) {
        log.info("用户微服务收到了订单信息:{}", JSONObject.toJSONString(order));
    }
}

@RocketMQMessageListener 注解,表示当前类是一个 RocketMQ 的消费者,在@RocketMQMessageListener 注解中配置了消费者组为 user-group,主题为 order-topic

4.2、订单微服务整合 RocketMQ

1、在订单微服务 shop-orderpom.xml 文件中添加 RocketMQ 的依赖

2、在订单微服务 shop-orderapplication.yml 文件中添加如下配置:

yml 复制代码
rocketmq:
  name-server: 127.0.0.1:9876
  producer:
    group: order-group

3、修改 OrderServiceImpl

java 复制代码
@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
   // ...

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrder(OrderParamVo orderParamVo) {
        // ...
        log.info("库存扣减成功");
        // 发送消息
        rocketMQTemplate.convertAndSend("order-topic", order);
    }
}

4.3、测试集成的 RocketMQ

1、分别启动 Nacos,Sentinel,ZipKin 和 RocketMQ

2、分别启动用户微服务、商品微服务、订单微服务和网关服务

3、在浏览器中输入localhost:10001/server-order/order/submit_order?userId=1001&productId=1001&count=1

4、查看用户微服务 shop-user 的控制台,发现会输出订单的信息,如下所示:

相关推荐
兔C29 分钟前
微信小程序的轮播图学习报告
学习·微信小程序·小程序
海海不掉头发36 分钟前
苍穹外卖-day05redis 缓存的学习
学习·缓存
小木_.2 小时前
【Python 图片下载器】一款专门为爬虫制作的图片下载器,多线程下载,速度快,支持续传/图片缩放/图片压缩/图片转换
爬虫·python·学习·分享·批量下载·图片下载器
一棵开花的树,枝芽无限靠近你2 小时前
【PPTist】组件结构设计、主题切换
前端·笔记·学习·编辑器
犬余2 小时前
设计模式之桥接模式:抽象与实现之间的分离艺术
笔记·学习·设计模式·桥接模式
啊瞑3 小时前
学习记录:配置mybatisplus的分页查询插件,mybatis-plus-jsqlparser 依赖
学习
码到成龚3 小时前
SQL server学习09-数据库编程(上)
数据库·学习
咖肥猫3 小时前
【ue5学习笔记2】在场景放入一个物体的蓝图输入事件无效?
笔记·学习·ue5
kitsch0x973 小时前
工具学习_Conan 安装第三方库
开发语言·python·学习
南宫生4 小时前
力扣-贪心-1【算法学习day.71】
java·学习·算法·leetcode