RocketMQ学习、部署及使用

在项目中会经常使用到消息队列,在日志领域和大数据领域中使用kafka、在普通常规项目领域使用rabbitmq,在项目中部署以及集成到业务逻辑,都有实操经验;也经常听说rocketmq用在金融订单等领域中,然而并没有在实际项目中使用上并没有用到,借此机会对rocket相关概念、架构等进行学习,并进行实际的部署以及集成使用,于此进行记录以便后续持续深入学习,并为后来者提供参考借鉴,文中不免疏漏之处,望读者予以指正,不胜感激!

1. 基本介绍

1.1 基本概念

RocketMQ 是一个队列模型的消息中间件,具有高性能、高可靠、高实时、分布式的特点。它是一个采用 Java 语言开发的分布式的消息系统,由阿里巴巴团队开发,在 2016 年底贡献给 Apache,成为了 Apache 的一个顶级项目。在阿里内部,RocketMQ 很好地服务了集团大大小小上千个应用,在每年的双十一当天,更有不可思议的万亿级消息通过 RocketMQ 流转。

1.2 特点

RocketMQ 是一款分布式、队列模型的消息中间件,具有以下特点:
能够保证严格的消息顺序。
提供丰富的消息拉取模式。
高效的订阅者水平扩展能力。
实时的消息订阅机制。
亿级消息堆积能力。

1.3 应用场景

Mq比较以及应用场景
目前主流的MQ主要是Rocketmq、kafka、Rabbitmq,Rocketmq相比于Rabbitmq、kafka具有主要优势特性有:
• 支持事务型消息(消息发送和DB操作保持两方的最终一致性,rabbitmq和kafka不支持)
• 支持结合rocketmq的多个系统之间数据最终一致性(多方事务,二方事务是前提)
• 支持18个级别的延迟消息(rabbitmq和kafka不支持)
• 支持指定次数和时间间隔的失败消息重发(kafka不支持,rabbitmq需要手动确认)
• 支持consumer端tag过滤,减少不必要的网络传输(rabbitmq和kafka不支持)
• 支持重复消费(rabbitmq不支持,kafka支持)

2. 架构原理

2.1 结构图

在这里插入图片描述

2.2 基本概念

整体的架构设计主要分为四大部分,分别是:Producer、Consumer、Broker、NameServer。

Producer:就是消息生产者,可以集群部署。它会先和 NameServer 集群中的随机一台建立长连接,得知当前要发送的 Topic 存在哪台 Broker Master上,然后再与其建立长连接,支持多种负载平衡模式发送消息;

Consumer:消息消费者,也可以集群部署。它也会先和 NameServer 集群中的随机一台建立长连接,得知当前要消息的 Topic 存在哪台 Broker Master、Slave上,然后它们建立长连接,支持集群消费和广播消费消息;

Broker:主要负责消息的存储、查询消费,支持主从部署,一个 Master 可以对应多个 Slave,Master 支持读写,Slave 只支持读。Broker 会向集群中的每一台 NameServer 注册自己的路由信息;

NameServer:是一个很简单的 Topic 路由注册中心,支持 Broker 的动态注册和发现,保存 Topic 和 Borker 之间的关系。通常也是集群部署,但是各 NameServer 之间不会互相通信, 各 NameServer 都有完整的路由信息,即无状态。

2.3 工作流

先启动 NameServer 集群,各 NameServer 之间无任何数据交互,Broker 启动之后会向所有 NameServer 定期(每 30s)发送心跳包,包括:IP、Port、TopicInfo,NameServer 会定期扫描 Broker 存活列表,如果超过 120s 没有心跳则移除此 Broker 相关信息,代表下线。
这样每个 NameServer 就知道集群所有 Broker 的相关信息,此时 Producer 上线从 NameServer 就可以得知它要发送的某 Topic 消息在哪个 Broker 上,和对应的 Broker (Master 角色的)建立长连接,发送消息。
Consumer 上线也可以从 NameServer 得知它所要接收的 Topic 是哪个 Broker ,和对应的 Master、Slave 建立连接,接收消息。

3. 安装部署

3.1 安装环境版本

环境:CentOS Linux release 7.9.2009 (Core)
版本:rocketmq-4.9.3
Jdk:jdk1.8.0_241

3.2 安装步骤

  1. 官网下载安装包
    在这里插入图片描述
  2. 解压
unzip rocketmq-all-4.9.3-bin-release.zip
  1. 启动NameServer
cd rocketmq-4.9.3/bin/
nohup sh mqnamesrv &
cat  nohup.out
tail -f ~/log/rocketmqlogs/namesrv.log

在这里插入图片描述
在这里插入图片描述
4. 启动broker

# 1. 进入bin目录
cd rocketmq-4.9.3/bin/
# 2. 启动broker
nohup sh mqbroker -n localhost:9876 &
# 3. 查看启动日志
tail -f ~/log/rocketmqlogs/broker.log
  1. 报错内存不足
# 编辑runbroker.sh和runserver.sh修改默认的 JVM大小
vim runbroker.sh
vim runserver.sh

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
6. 发送消息

# 1、 设置环境变量
export NAMESRV_ADDR=localhost:9876
# 2、使用安装包的DEMO发送消息
sh tools.sh org.apache.rocketmq.example.quickstart.Producer
  1. 接收消息
## 1、 设置环境变量
export NAMESRV_ADDR=localhost:9876
##  2、使用安装包的DEMO发送消息
sh tools.sh org.apache.rocketmq.example.quickstart.Consumer
  1. 关闭RocketMQ
关闭nameserver
sh mqshutdown namesrv

关闭broker
sh mqshutdown broker

4. RocketMQ Console 控制台

下载地址:
https://github.com/apache/rocketmq-externals/branches
在这里插入图片描述
mvn clean package -Dmaven.test.skip=true
java -jar target/rocketmq-console-ng-1.0.0.jar

在这里插入图片描述

5. springboot集成使用

5.1 引入jar依赖

<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-spring-boot-starter</artifactId>
    <version>2.0.3</version>
</dependency>

5.2 配置

rocketmq:
  name-server: 192.168.109.138:9876
  producer:
    # 生产组
    group: demo-group
    # 发送消息超时时间,默认 3000
    sendMessageTimeout: 3000
    # 发送消息失败重试次数,默认2
    retryTimesWhenSendFailed: 2
    # 发送异步消息失败重试次数,默认2
    retryTimesWhenSendAsyncFailed: 2

5.3 生产者,发送消息

@Component
public class RocketUtil {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    
    public String send(String message){
        SendResult sendResult = rocketMQTemplate.syncSend("topic_test" + ":" + "tag_1",message);
        return JSONObject.toJSONString(sendResult);
    }
    
}

5.4 消费者

@Service
@RocketMQMessageListener(topic = "topic_test", selectorExpression = "tag_1", consumerGroup = "QueueHandler")
public class QueueListener implements RocketMQListener<MessageExt> {

    private static final Logger logger = LoggerFactory.getLogger(QueueListener.class);

    public void onMessage(MessageExt message) {
        String body = new String(message.getBody());
        logger.info("消息内容:"+ body);
        logger.info("消息ID:"+message.getMsgId());
    }
}

6.参考资料

https://rocketmq.apache.org/

猜你喜欢

转载自blog.csdn.net/shy871/article/details/121997187