Rockermq的部署与使用(0-1)

RocketMQ ​ 是阿里巴巴开源的一款 ​分布式消息中间件,具有高吞吐、低延迟、高可用等特点,广泛应用于多个领域,包括异步通信解耦、企业解决方案、金融支付、电信、电子商务、快递物流、广告营销、社交、即时通信、移动应用、手游、视频、物联网、车联网等。

一.RockerMQ的概念:

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

1. 架构分析:

  • 生产者(Producer):负责产生消息,生产者向消息服务器发送由业务应用程序系统生成的消息。
  • 消费者(Consumer):负责消费消息,消费者从消息服务器拉取 信息并将其输入用户应用程序。
  • 消息服务器(Broker):是消息存储中心,主要作用是接收来自 Producer 的消息并存储, Consumer 从这里取得消息。
  • 名称服务器(NameServer):用来保存 Broker 相关 Topic 等元信息并给 Producer ,提供 Consumer 查找 Broker 信息。

2.整体流程:

1、首先启动 Namesrv( 名称服务器**)**,Namesrv 起来后监听端口,等待 Broker、Producer、Consumer 连上来,相当于一个路由控制中心。

2、Broker 启动,跟所有的 Namesrv保持长连接,定时发送心跳包

心跳包中,包含当前 Broker 信息(IP+端口等)以及存储所有 Topic 信息。 注册成功后,Namesrv 集群中就有 Topic 跟 Broker 的映射关系。

3、收发消息前,先创建 Topic 。创建 Topic 时,需要指定该 Topic 要存储在哪些 Broker上。也可以在发送消息时自动创建Topic。

4、Producer 发送消息。

启动时,先跟 Namesrv 集群中的其中一台建立长连接,并从Namesrv 中获取当前发送的 Topic 存在哪些 Broker 上,然后跟对应的 Broker 建立长连接,直接向 Broker 发消息。

5、Consumer 消费消息。

Consumer 跟 Producer 类似。跟其中一台 Namesrv 建立长连接,获取当前订阅 Topic 存在哪些 Broker 上,然后直接跟 Broker 建立连接通道,开始消费消息。

二.Rockermq单机部署:

1.安装解压包:

rocketmq-all-4.6.0-source-release.zip

点击横杠即可下载安装包。

2.Windows部署 / Linux部署:

(1)Windows部署:

解压后使用 Maven 编译 RocketMQ 源码。命令行操作如下:

复制代码
# 进入 RocketMQ 源码目录
$ cd rocketmq-all-4.6.0-source-release

# Maven 编译 RocketMQ ,并跳过测试。耐心等待...
$ mvn -Prelease-all -DskipTests clean install -U

随后进入.\bin\mqnamesrv.cmd来启动Namesrv,如果报错 Java not found,请检查 JAVA_HOME 环境变量。

复制代码
.\mqnamesrv.cmd

正常会出现下图:

随后新建一个CMD窗口(不要关闭 NameServer),进入 bin 目录,启动Broker:

复制代码
mqbroker.cmd -c ..\conf\broker.conf -n localhost:9876

(2)Linux部署:

使用wget命令下载,随后使用unzip命令解压:

复制代码
# 下载
$ wget wget http://mirror.bit.edu.cn/apache/rocketmq/4.6.0/rocketmq-all-4.6.0-source-release.zip

# 解压
$ unzip rocketmq-all-4.6.0-source-release.zip

随后同样使用 Maven 编译 RocketMQ 源码。命令行操作如下:

复制代码
# 进入 RocketMQ 源码目录
$ cd rocketmq-all-4.6.0-source-release

# Maven 编译 RocketMQ ,并跳过测试。耐心等待...
$ mvn -Prelease-all -DskipTests clean install -U

编译完成,在我们进入 distribution 目录下,就可以看到 RocketMQ 的发布包了。命令行操作如下:

复制代码
# 进入 distribution 目录下
$ cd distribution/target/rocketmq-4.6.0/rocketmq-4.6.0

# 打印目录
$ ls
40 -rwxr-xr-x   1 yunai  staff  17336 Nov 19 20:59 LICENSE
 8 -rwxr-xr-x   1 yunai  staff   1338 Nov 19 20:59 NOTICE
16 -rwxr-xr-x   1 yunai  staff   4225 Nov 19 20:59 README.md
 0 drwxr-xr-x   6 yunai  staff    192 Dec  3 12:48 benchmark # 性能基准测试
 0 drwxr-xr-x  30 yunai  staff    960 Nov 19 20:59 bin # 执行脚本
 0 drwxr-xr-x  12 yunai  staff    384 Nov 19 20:59 conf # 配置文件
 0 drwxr-xr-x  36 yunai  staff   1152 Dec  3 12:48 lib # RocketMQ jar 包

随后启动Namesrv:

复制代码
nohup sh bin/mqnamesrv &

启动完成后,查看日志:

复制代码
# 查看 Namesrv 日志。
$ tail -f ~/logs/rocketmqlogs/namesrv.log

2019-12-03 12:58:04 INFO main - The Name Server boot success. serializeType=JSON

默认情况下,Namesrv 日志文件所在地址为 ~/logs/rocketmqlogs/namesrv.log 。如果想要自定义,可以通过 conf/logback_namesrv.xml 配置文件来进行修改。

随后启动broker:

conf 目录下,RocketMQ 提供了多种 Broker 的配置文件:

  • broker.conf :单主,异步刷盘。
  • 2m/ :双主,异步刷盘。
  • 2m-2s-async/ :两主两从,异步复制,异步刷盘。
  • 2m-2s-sync/ :两主两从,同步复制,异步刷盘。
  • dledger/Dledger 集群,至少三节点。

这里,我们只启动一个 RocketMQ Broker 服务,所以使用 broker.conf 配置文件。命令行操作如下:

复制代码
nohup sh bin/mqbroker -c conf/broker.conf  -n 127.0.0.1:9876 &
  • 通过 -c 参数,配置读取的主 Broker 配置。

  • 通过 -n 参数,设置 RocketMQ Namesrv 地址。

3.测试消息:

(1)测试发送消息:

通过使用 bin/tools.sh 工具类,实现测试发送消息。命令行操作如下:

复制代码
# 设置 Namesrv 服务器的地址
export NAMESRV_ADDR=127.0.0.1:9876

# 执行生产者 Producer 发送测试消息
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer

如果发送成功,我们会看到大量成功的发送日志。

复制代码
SendResult [sendStatus=SEND_OK, msgId=FE800000000000004F2B5386138462F500000D7163610D67E7F100F4, offsetMsgId=C0A8032C00002A9F000000000000D7EE, messageQueue=MessageQueue [topic=TopicTest, brokerName=broker-a, queueId=0], queueOffset=61]
SendResult [sendStatus=SEND_OK, msgId=FE800000000000004F2B5386138462F500000D7163610D67E7F200F5, offsetMsgId=C0A8032C00002A9F000000000000D8D1, messageQueue=MessageQueue [topic=TopicTest, brokerName=broker-a, queueId=1], queueOffset=61]

通过发送结果为 sendStatus=SEND_OK 状态,说明消息都发送成功了。

(2)测试消费消息:

通过使用 bin/tools.sh 工具类,实现测试消费消息。命令行操作如下:

复制代码
# 设置 Namesrv 服务器的地址
export NAMESRV_ADDR=127.0.0.1:9876

# 执行消费者 Consumer 消费测试消息
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer

如果消费成功,我们会看到大量成功的消费日志。

复制代码
ConsumeMessageThread_4 Receive New Messages: [MessageExt [queueId=2, storeSize=227, queueOffset=131, sysFlag=0, bornTimestamp=1575354513732, bornHost=/192.168.3.44:55510, storeTimestamp=1575354513733, storeHost=/192.168.3.44:10911, msgId=C0A8032C00002A9F000000000001D1FC, commitLogOffset=119292, bodyCRC=1549304357, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='TopicTest', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=145, CONSUME_START_TIME=1575354867104, UNIQ_KEY=FE800000000000004F2B5386138462F500000D7163610D67E944020E, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 82, 111, 99, 107, 101, 116, 77, 81, 32, 53, 50, 54], transactionId='null'}]]
ConsumeMessageThread_3 Receive New Messages: [MessageExt [queueId=2, storeSize=227, queueOffset=130, sysFlag=0, bornTimestamp=1575354513729, bornHost=/192.168.3.44:55510, storeTimestamp=1575354513729, storeHost=/192.168.3.44:10911, msgId=C0A8032C00002A9F000000000001CE70, commitLogOffset=118384, bodyCRC=1530218044, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='TopicTest', flag=0, properties={MIN_OFFSET=0, MAX_OFFSET=145, CONSUME_START_TIME=1575354867103, UNIQ_KEY=FE800000000000004F2B5386138462F500000D7163610D67E941020A, CLUSTER=DefaultCluster, WAIT=true, TAGS=TagA}, body=[72, 101, 108, 108, 111, 32, 82, 111, 99, 107, 101, 116, 77, 81, 32, 53, 50, 50], transactionId='null'}]]

通过 ConsumeMessageThread_4ConsumeMessageThread_3 线程名,我们可以看出,目前是进行并发消费消息。

三.Rockermq的简单使用实例:

(1)项目结构:

复制代码
rocketmq-demo/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/example/
│   │   │       ├── producer/OrderProducer.java   # 生产者
│   │   │       ├── consumer/OrderConsumer.java  # 消费者
│   │   │       └── RocketmqDemoApplication.java # 启动类
│   │   └── resources/
│   │       └── application.yml                  # 配置文件
│   └── test/
└── pom.xml                                      # Maven依赖

(2)添加依赖:

XML 复制代码
<dependencies>
    <!-- Spring Boot Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <!-- RocketMQ Starter -->
    <dependency>
        <groupId>org.apache.rocketmq</groupId>
        <artifactId>rocketmq-spring-boot-starter</artifactId>
        <version>2.2.3</version>
    </dependency>
</dependencies>

(3)编写配置文件:

XML 复制代码
rocketmq:
  name-server: localhost:9876  # NameServer地址
  producer:
    group: order-producer-group  # 生产者组
  consumer:
    group: order-consumer-group  # 消费者组
    topic: order-topic           # 订阅的Topic

(4)编写生产者代码:

java 复制代码
package com.example.producer;

import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class OrderProducer {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    public void sendOrderMessage(String orderId) {
        // 发送消息(Topic: order-topic, Tag: pay)
        rocketMQTemplate.convertAndSend("order-topic:pay", "订单支付成功,订单ID: " + orderId);
        System.out.println("生产者发送消息: " + orderId);
    }
}

(5)编写消费者代码:

java 复制代码
package com.example.consumer;

import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Component;

@Component
@RocketMQMessageListener(
        topic = "order-topic",          // 监听的Topic
        selectorExpression = "pay",     // 过滤Tag=pay的消息
        consumerGroup = "order-consumer-group"
)
public class OrderConsumer implements RocketMQListener<String> {

    @Override
    public void onMessage(String message) {
        System.out.println("消费者收到消息: " + message);
    }
}

(6)启动类:

java 复制代码
package com.example;

import com.example.producer.OrderProducer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class RocketmqDemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(RocketmqDemoApplication.class, args);
        
        // 测试发送消息
        OrderProducer producer = context.getBean(OrderProducer.class);
        producer.sendOrderMessage("1001");  // 发送订单ID=1001
    }
}
相关推荐
bing_15828 分钟前
Spring MVC @CookieValue 注解怎么用?
java·spring·mvc
Aurora_NeAr33 分钟前
Spring MVC设计与实现
java·spring·mvc
qq_38413684438 分钟前
SpringBoot的启动流程
java·spring boot·后端
码上飞扬44 分钟前
Java大师成长计划之第12天:性能调优与GC原理
java·开发语言
264玫瑰资源库1 小时前
网狐旗舰大联盟组件源码私测笔记:结构分层、UI重构与本地实操全流程
java·前端·数据库·笔记·ui·重构
_Djhhh1 小时前
【基础算法】二分查找的多种写法
java·数据结构·算法·二分查找
chilling heart1 小时前
JAVA---继承
java·开发语言·学习
黄雪超1 小时前
JVM——JVM是怎么实现invokedynamic的?
java·开发语言·jvm
Rubypyrrha2 小时前
Spring MVC的工作流程, DispatcherServlet 的工作流程
java·spring·mvc
小园子的小菜2 小时前
探秘 RocketMQ 的 DLedgerServer:MemberState 的技术解析与深度剖析
java·rocketmq·java-rocketmq