rocketmq基础

CentOS-7环境

rocketmq4.9.5

一、搭建rocketmq单机服务

官网地址:RocketMQ · 官方网站 | RocketMQ

我的理解:rocketmq搭建需要开启两个Java程序,所以就需要jdk环境,一个是nameserver服务,用于注册broker的元数据信息,另一个broker服务用于实际存储消息;生产者通过nameserver找到broker地址,broker再把消息推送给消费者

1、jdk环境的安装(rocketmq运行需要)

通过网盘分享的文件:jdk-8u161-linux-x64.tar.gz

链接: https://pan.baidu.com/s/1zrIas_-xzj8ZXkscJBSvfQ 提取码: yac1

1)解压

bash 复制代码
tar -zxvf jdk-8u161-linux-x64.tar.gz

2)配置环境变量

打开用户级环境变量配置文件,也可以打开系统级的环境变量配置文件/etc/profile,是一样

bash 复制代码
vim ~/.bash_profile 
# 如果进入文件想要查看文件行号 输入如下
:set nu

追加如下内容

bash 复制代码
export JAVA_HOME=/app/jdk/jdk1.8.0_161
export JRE_HOME=$JAVA_HOME/jre
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH

执行配置生效命令

bash 复制代码
source ~/.bash_profile

3)验证安装

bash 复制代码
java -version

2、maven环境的安装

这个后面用于rocketmq可视化界面的源码打成jar包

下载地址:Download Apache Maven -- Maven

1)解压

复制代码
tar -zxvf apache-maven-3.9.9-bin.tar.gz

2)配置环境变量

bash 复制代码
vim ~/.bash_profile 
# 如果进入文件想要查看文件行号 输入如下
:set nu

追加如下内容

bash 复制代码
export MAVEN_HOME=/app/maven/apache-maven-3.9.9
export PATH=$MAVEN_HOME/bin:$PATH

执行配置生效命令

bash 复制代码
source ~/.bash_profile

3)配置阿里云镜像

bash 复制代码
vim settings.xml
bash 复制代码
<mirror>
    <id>alimaven</id>
    <mirrorOf>*</mirrorOf>
    <name>Aliyun Global Maven</name>
    <url>https://maven.aliyun.com/repository/public/</url>
</mirror>

<localRepository>/path/to/local/repo</localRepository>也需要指定一下

4)验证安装

bash 复制代码
mvn -v

3、rocketmq单机搭建

rocketmq下载地址:下载 | RocketMQ

RocketMQ建议的运行环境需要至少12G的内存,这是生产环境比较理想的资源配置

1)配置NameServer的jvm参数

bash 复制代码
# 切换到rocketmq的bin目录下打开runserver.sh文件
vim runserver.sh
bash 复制代码
JAVA_OPT="${JAVA_OPT} -server -Xms512m -Xmx512m -Xmn256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"

2)配置Broker的jvm参数

bash 复制代码
# 切换到rocketmq的bin目录下打开runbroker.sh文件
vim runbroker.sh
bash 复制代码
JAVA_OPT="${JAVA_OPT} -server -Xms8g -Xmx8g"
修改为:
JAVA_OPT="${JAVA_OPT} -server -Xms1g -Xmx1g"

3)启动

1】启动nameserver服务
bash 复制代码
# 切换到rocketmq的home目录下,启动nameserver服务
nohup bin/mqnamesrv &
2】启动broker服务
bash 复制代码
# 切换到rocketmq的conf目录,修改broker.conf文件
vim broker.conf
# 追加如下行(如果生产者尝试向一个不存在的主题发送消息,消息系统会自动创建这个主题,而不需要管理员事先手动创建)
autoCreateTopicEnable=true
bash 复制代码
# 切换到rocketmq的home目录下,启动broker服务
nohup bin/mqbroker &

如果服务器有多张网卡, 就需要配置brokerIP1=外网ip,这样才能通过这个ip访问到服务器上的rocketmq服务
注:1、在实际服务部署时,通常会将RocketMQ的部署地址添加到环境变量当中。例如使用vi ~/.bash_profile指令,添加以下内容。

export ROCKETMQ_HOME=/app/rocketmq/rocketmq-all-4.9.5-bin-releasePATH=ROCKETMQ_HOME/bin:PATHexport PATH

这样就不必每次进入RocketMQ的安装目录了。直接可以使用mqnamesrv 和mqbroker指令。

2、停止RocketMQ服务可以通过mqshutdown指令进行

bin/mqshutdown namesrv # 关闭nameserver服务

bin/mqshutdown broker # 关闭broker服务

通过jps指令查看服务启动状态

二、快速实现消息收发

1、通过命令实现消息收发

1)指定nameserver地址

bash 复制代码
vi ~/.bash_profile

追加如下内容

bash 复制代码
export NAMESRV_ADDR='localhost:9876'

执行配置生效命令

bash 复制代码
source ~/.bash_profile

2)生产者发送消息

bash 复制代码
# 切换到rocketmq的home目录下执行(默认往RocketMQ中发送1000条消息)
bin/tools.sh org.apache.rocketmq.example.quickstart.Producer

3)消费者接收消息

bash 复制代码
# 切换到rocketmq的home目录下执行
bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer

2、搭建maven项目实现消息收发

1)引入maven依赖

XML 复制代码
<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-client</artifactId>
    <version>4.9.5</version>
</dependency>

2)生产者客户端代码

java 复制代码
public class Producer {

    public static void main(String[] args) throws MQClientException, InterruptedException {
        //初始化一个消息生产者
        DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name");
        // 指定nameserver地址
        producer.setNamesrvAddr("192.168.225.134:9876");
        // 启动消息生产者服务
        producer.start();
        for (int i = 0; i < 2; i++) {
            try {
                // 创建消息。消息由Topic,Tag和body三个属性组成,其中Body就是消息内容
                Message msg = new Message("TopicTest","TagA",("Hello RocketMQ " +i).getBytes(RemotingHelper.DEFAULT_CHARSET));
                //发送消息,获取发送结果
                SendResult sendResult = producer.send(msg);
                System.out.printf("%s%n", sendResult);
            } catch (Exception e) {
                e.printStackTrace();
                Thread.sleep(1000);
            }
        }
        //消息发送完后,停止消息生产者服务。
        producer.shutdown();
    }
}

3)消费者客户端代码

java 复制代码
public class Consumer {
    public static void main(String[] args) throws InterruptedException, MQClientException {
        //构建一个消息消费者
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name_4");
        //指定nameserver地址
       consumer.setNamesrvAddr("192.168.225.134:9876");
       consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
        // 订阅一个感兴趣的话题,这个话题需要与消息的topic一致
        consumer.subscribe("TopicTest", "*");
        // 注册一个消息回调函数,消费到消息后就会触发回调。
        consumer.registerMessageListener(new MessageListenerConcurrently() {
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,ConsumeConcurrentlyContext context) {
    msgs.forEach(messageExt -> {
                    try {
                        System.out.println("收到消息:"+new String(messageExt.getBody(), RemotingHelper.DEFAULT_CHARSET));
                    } catch (UnsupportedEncodingException e) {}
                });
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        //启动消费者服务
        consumer.start();
        System.out.print("Consumer Started");
    }
}

三、搭建rocketmq可视化界面

rocketmq下载地址:下载 | RocketMQ,在最下面找dashboard

1、编译

把源码包下载后,解压之后,切换到rocketmq-dashboard-2.0.0-source-release项目目录下,执行如下命令

java 复制代码
mvn clean package -Dmaven.test.skip=true

rocketmq-dashboard-2.0.0-source-release项目目录下生成target/rocketmq-dashboard-2.0.0.jar文件

2、运行

在jar文件所在目录新建application.yml指定nameserver地址,内容如下

java 复制代码
rocketmq: 
  config: 
    namesrvAddrs: 
      - 192.168.225.134:9876 

接下来执行如下命令

java 复制代码
java -jar rocketmq-dashboard-2.0.0.jar

3、管理界面

运行后访问http://192.168.225.134:8080/

四、分布式集群搭建

集群结构图(两主两从异步)

配置主机/etc/hosts如下

bash 复制代码
cat /etc/hosts
192.168.225.134 worker-rocketmq1
192.168.225.135 worker-rocketmq2
192.168.225.136 worker-rocketmq3

1、配置nameserver

nameserver不需要做特别的配置,worker-rocketmq1已经配置了,只需要配置另外两台就行了

1)新建目录

在worker-rocketmq2和worker-rocketmq3执行如下命令

复制代码
mkdir -p /app/rocketmq
mkdir -p /app/jdk

2)复制文件

在worker-rocketmq1执行如下命令,把文件复制到worker-rocketmq2和worker-rocketmq3上

bash 复制代码
#在/app/rocket目录下执行
scp -r rocketmq-all-4.9.5-bin-release root@worker-rocketmq2:/app/rocketmq
scp -r /app/jdk/jdk1.8.0_161/ root@worker-rocketmq2:/app/jdk
scp -r rocketmq-all-4.9.5-bin-release root@worker-rocketmq3:/app/rocketmq
scp -r /app/jdk/jdk1.8.0_161/ root@worker-rocketmq3:/app/jdk

3)配置

jdk配置

bash 复制代码
vim ~/.bash_profile

export JAVA_HOME=/app/jdk/jdk1.8.0_161
export JRE_HOME=$JAVA_HOME/jre
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH

source ~/.bash_profile

nameserver的jvm参数之前改过了,所以就这样

2、配置broker

1)broker-a配置

在worker-rocketmq1执行如下命令

bash 复制代码
vim /app/rocketmq/rocketmq-all-4.9.5-bin-release/conf/2m-2s-async/broker-a.properties

配置如下

bash 复制代码
#所属集群名字,名字一样的节点就在同一个集群内
brokerClusterName=rocketmq-cluster
#broker名字,名字一样的节点就是一组主从节点。
brokerName=broker-a
#brokerid,0就表示是Master,>0的都是表示 Slave
brokerId=0
#nameServer地址,分号分割
namesrvAddr=worker-rocketmq1:9876;worker-rocketmq2:9876;worker-rocketmq3:9876
#是否允许 Broker 自动创建Topic,建议线下开启,线上关闭
autoCreateTopicEnable=true
deleteWhen=04
fileReservedTime=120
#存储路径
storePathRootDir=/app/rocketmq/store
storePathCommitLog=/app/rocketmq/store/commitlog
storePathConsumeQueue=/app/rocketmq/store/consumequeue
storePathIndex=/app/rocketmq/store/index
storeCheckpoint=/app/rocketmq/store/checkpoint
abortFile=/app/rocketmq/store/abort
#Broker 的角色
brokerRole=ASYNC_MASTER
flushDiskType=ASYNC_FLUSH
#Broker 对外服务的监听端口
listenPort=10911

2)broker-a-s配置

在worker-rocketmq2执行如下命令

bash 复制代码
vim /app/rocketmq/rocketmq-all-4.9.5-bin-release/conf/2m-2s-async/broker-a-s.properties

配置如下

bash 复制代码
#所属集群名字,名字一样的节点就在同一个集群内
brokerClusterName=rocketmq-cluster
#broker名字,名字一样的节点就是一组主从节点。
brokerName=broker-a
#brokerid,0就表示是Master,>0的都是表示 Slave
brokerId=1
#nameServer地址,分号分割
namesrvAddr=worker-rocketmq1:9876;worker-rocketmq2:9876;worker-rocketmq3:9876
#是否允许 Broker 自动创建Topic,建议线下开启,线上关闭
autoCreateTopicEnable=true
deleteWhen=04
fileReservedTime=120
#存储路径
storePathRootDir=/app/rocketmq/storeSlave
storePathCommitLog=/app/rocketmq/storeSlave/commitlog
storePathConsumeQueue=/app/rocketmq/storeSlave/consumequeue
storePathIndex=/app/rocketmq/storeSlave/index
storeCheckpoint=/app/rocketmq/storeSlave/checkpoint
abortFile=/app/rocketmq/storeSlave/abort
#Broker 的角色
brokerRole=SLAVE
flushDiskType=ASYNC_FLUSH
#Broker 对外服务的监听端口
listenPort=11011

3)broker-b配置

在worker-rocketmq2执行如下命令

bash 复制代码
vim /app/rocketmq/rocketmq-all-4.9.5-bin-release/conf/2m-2s-async/broker-b.properties

配置如下

bash 复制代码
#所属集群名字,名字一样的节点就在同一个集群内
brokerClusterName=rocketmq-cluster
#broker名字,名字一样的节点就是一组主从节点。
brokerName=broker-b
#brokerid,0就表示是Master,>0的都是表示 Slave
brokerId=0
#nameServer地址,分号分割
namesrvAddr=worker-rocketmq1:9876;worker-rocketmq2:9876;worker-rocketmq3:9876
#是否允许 Broker 自动创建Topic,建议线下开启,线上关闭
autoCreateTopicEnable=true
deleteWhen=04
fileReservedTime=120
#存储路径
storePathRootDir=/app/rocketmq/store
storePathCommitLog=/app/rocketmq/store/commitlog
storePathConsumeQueue=/app/rocketmq/store/consumequeue
storePathIndex=/app/rocketmq/store/index
storeCheckpoint=/app/rocketmq/store/checkpoint
abortFile=/app/rocketmq/store/abort
#Broker 的角色
brokerRole=ASYNC_MASTER
flushDiskType=ASYNC_FLUSH
#Broker 对外服务的监听端口
listenPort=10911

4)broker-b-s配置

在worker-rocketmq1执行如下命令

bash 复制代码
vim /app/rocketmq/rocketmq-all-4.9.5-bin-release/conf/2m-2s-async/broker-b-s.properties

配置如下

bash 复制代码
#所属集群名字,名字一样的节点就在同一个集群内
brokerClusterName=rocketmq-cluster
#broker名字,名字一样的节点就是一组主从节点。
brokerName=broker-b
#brokerid,0就表示是Master,>0的都是表示 Slave
brokerId=1
#nameServer地址,分号分割
namesrvAddr=worker-rocketmq1:9876;worker-rocketmq2:9876;worker-rocketmq3:9876
#是否允许 Broker 自动创建Topic,建议线下开启,线上关闭
autoCreateTopicEnable=true
deleteWhen=04
fileReservedTime=120
#存储路径
storePathRootDir=/app/rocketmq/storeSlave
storePathCommitLog=/app/rocketmq/storeSlave/commitlog
storePathConsumeQueue=/app/rocketmq/storeSlave/consumequeue
storePathIndex=/app/rocketmq/storeSlave/index
storeCheckpoint=/app/rocketmq/storeSlave/checkpoint
abortFile=/app/rocketmq/storeSlave/abort
#Broker 的角色
brokerRole=SLAVE
flushDiskType=ASYNC_FLUSH
#Broker 对外服务的监听端口
listenPort=11011

这样就完成了2主2从集群的配置。配置过程汇总有几个需要注意的配置项:

  • store开头的一系列配置:表示RocketMQ的存盘文件地址。在同一个机器上需要部署多个Broker服务时,不同服务的存储目录不能相同。

  • listenPort:表示Broker对外提供服务的端口。这个端口默认是10911。在同一个机器上部署多个Broker服务时,不同服务占用的端口也不能相同。

  • 如果你使用的是多网卡的服务器,比如阿里云上的云服务器,那么就需要在配置文件中增加配置一个brokerIP1属性,指向所在机器的外网网卡地址。

3、启动nameserver

worker-rocketmq1、worker-rocketmq2、worker-rocketmq3都执行如下命令

bash 复制代码
# 切换到rocketmq的home目录下,启动nameserver服务
nohup bin/mqnamesrv &

4、启动broker

worker-rocketmq1启动broker-a和broker-b-s

bash 复制代码
# 切换到rocketmq的home目录下
nohup bin/mqbroker -c ./conf/2m-2s-async/broker-a.properties &
nohup bin/mqbroker -c ./conf/2m-2s-async/broker-b-s.properties &

worker-rocketmq2启动broker-b和broker-a-s

bash 复制代码
nohup bin/mqbroker -c ./conf/2m-2s-async/broker-b.properties &
nohup bin/mqbroker -c ./conf/2m-2s-async/broker-a-s.properties &

5、检查集群服务状态

bash 复制代码
#切换到rocketmq的home目录下(需要配置NAMESRV环境变量)
bin/mqadmin clusterList

之前的dashboard可视化界面,application.yml重新指定nameserver地址

bash 复制代码
rocketmq: 
  config: 
    namesrvAddrs: 
      - worker-rocketmq1:9876 
      - worker-rocketmq2:9876
      - worker-rocketmq3:9876

运行后运行情况

五、高可用集群搭建

上面集群不会自动主从切换(优点就是服务宕机消息不会丢失),而rocketmq还有一种Dledger集群基于Raft协议(多数选举出主节点),可以实现主从自动切换,意味着集群中必须要超过半数以上节点正常运行集群才能正常工作(我觉得大概知道怎么回事就行了,再研究Dledger集群原理没多大意义)

注:在RocketMQ运行包的bin/dledger目录下,RocketMQ还提供了一个fast-try.sh脚本。这个脚本会指定conf/deldger目录下的配置文件,直接启动有三个broker服务的Dledger集群。每个集群指定的内存大小占用1G。

在conf/dledger目录下,RocketMQ默认给出了三个配置文件,这三个配置文件可以在单机情况下直接部署成一个具有三个broker服务的Dledger集群,我们只需要按照这个配置进行修改即可。

1、nameserver配置

搭建过的nameserver不用动了

2、broker配置

在三台机器的conf/dledger目录下,都创建一个broker.conf文件

1)worker-rocketmq1配置

执行如下命令

bash 复制代码
vim /app/rocketmq/rocketmq-all-4.9.5-bin-release/conf/dledger/broker.conf

配置如下

bash 复制代码
brokerClusterName = RaftCluster
brokerName=RaftNode00
listenPort=30911
namesrvAddr=worker-rocketmq1:9876;worker-rocketmq2:9876;worker-rocketmq3:9876
storePathRootDir=/app/rocketmq/storeDledger/
storePathCommitLog=/app/rocketmq/storeDledger/commitlog
storePathConsumeQueue=/app/rocketmq/storeDledger/consumequeue
storePathIndex=/app/rocketmq/storeDledger/index
storeCheckpoint=/app/rocketmq/storeDledger/checkpoint
abortFile=/app/rocketmq/storeDledger/abort
enableDLegerCommitLog=true
dLegerGroup=RaftNode00
dLegerPeers=n0-worker-rocketmq1:40911;n1-worker-rocketmq2:40911;n2-worker-rocketmq3:40911
## must be unique
dLegerSelfId=n0
sendMessageThreadPoolNums=16

2)worker-rocketmq2配置

执行如下命令

bash 复制代码
vim /app/rocketmq/rocketmq-all-4.9.5-bin-release/conf/dledger/broker.conf

配置如下

bash 复制代码
brokerClusterName = RaftCluster
brokerName=RaftNode00
listenPort=30911
namesrvAddr=worker-rocketmq1:9876;worker-rocketmq2:9876;worker-rocketmq3:9876
storePathRootDir=/app/rocketmq/storeDledger/
storePathCommitLog=/app/rocketmq/storeDledger/commitlog
storePathConsumeQueue=/app/rocketmq/storeDledger/consumequeue
storePathIndex=/app/rocketmq/storeDledger/index
storeCheckpoint=/app/rocketmq/storeDledger/checkpoint
abortFile=/app/rocketmq/storeDledger/abort
enableDLegerCommitLog=true
dLegerGroup=RaftNode00
dLegerPeers=n0-worker-rocketmq1:40911;n1-worker-rocketmq2:40911;n2-worker-rocketmq3:40911
## must be unique
dLegerSelfId=n1
sendMessageThreadPoolNums=16

3)worker-rocketmq3配置

执行如下命令

bash 复制代码
vim /app/rocketmq/rocketmq-all-4.9.5-bin-release/conf/dledger/broker.conf

配置如下

bash 复制代码
brokerClusterName = RaftCluster
brokerName=RaftNode00
listenPort=30911
namesrvAddr=worker-rocketmq1:9876;worker-rocketmq2:9876;worker-rocketmq3:9876
storePathRootDir=/app/rocketmq/storeDledger/
storePathCommitLog=/app/rocketmq/storeDledger/commitlog
storePathConsumeQueue=/app/rocketmq/storeDledger/consumequeue
storePathIndex=/app/rocketmq/storeDledger/index
storeCheckpoint=/app/rocketmq/storeDledger/checkpoint
abortFile=/app/rocketmq/storeDledger/abort
enableDLegerCommitLog=true
dLegerGroup=RaftNode00
dLegerPeers=n0-worker-rocketmq1:40911;n1-worker-rocketmq2:40911;n2-worker-rocketmq3:40911
## must be unique
dLegerSelfId=n2
sendMessageThreadPoolNums=16

这里对几个需要重点关注的配置项,做下介绍:

  • enableDLegerCommitLog: 是否启动Dledger。true表示启动

  • namesrvAddr: 指定nameserver地址

  • dLedgerGroup: Dledger Raft Group的名字,建议跟brokerName保持一致。

  • dLedgerPeers: Dledger Group内各个服务节点的地址及端口信息。同一个Group内的各个节点配置必须要保持一致。

  • dLedgerSelfId: Dledger节点ID,必须属于dLedgerPeers中的一个。同一个Group内的各个节点必须不能重复。

  • sendMessageThreadPoolNums:dLedger内部发送消息的线程数,建议配置成cpu核心数。

  • store开头的一系列配置: 这些是配置dLedger集群的消息存盘目录。如果你是从主从架构升级成为dLedger架构,那么这个地址可以指向之前搭建住主从架构的地址。dLedger集群会兼容主从架构集群的消息格式,只不过主从架构的消息无法享受dLedger集群的两阶段同步功能。

3、启动

nameserver之前启动过了,可参考上面的nameserver启动

三台机器worker-rocketmq1、worker-rocketmq2、worker-rocketmq3都切换到rocketmq的home目录下执行

bash 复制代码
nohup bin/mqbroker -c conf/dledger/broker.conf &

4、检查集群服务状态

dashboard控制台可以查看到集群的运行状态

leader节点执行bin/mqshutdown broker后的结果

Dledger集群如何防止脑裂问题的

  • 多数派选举:选举领导者时遵循多数派原则,确保同一时刻集群最多只有一个领导者。
  • 任期机制:通过单调递增的任期号,让节点优先处理高任期号请求,避免旧领导者在新任期工作。
  • 心跳机制:领导者定期发心跳,跟随者若未按时收到则发起选举,及时发现领导者故障。
  • 日志复制与检查:领导者复制日志到跟随者,多数节点复制成功才标记提交,节点会检查并同步日志,保证集群状态一致。
相关推荐
dengjiayue5 天前
kafka 与 RocketMQ对比
分布式·kafka·rocketmq
HPF_995 天前
RabbitMQ、RocketMQ 和 Kafka 的消息特性对比
kafka·rabbitmq·rocketmq
A初夏15 天前
Linux 部署 rocketmq centos7
rocketmq
孫治AllenSun6 天前
【RocketMQ&&RocketMQ Dashbord】Springboot整合RocketMQ
spring boot·rocketmq·java-rocketmq
逍遥德7 天前
【数据库事务、消息队列事务、Redis 事务、Spring 事务 详细分析】
数据库·redis·spring·rabbitmq·rocketmq
Gary_Tam9 天前
RocketMQ可视化工具使用 - Dashboard(保姆级教程)
rocketmq
嗯嗲和滴9 天前
消息队列(Kafka及RocketMQ等对比联系)
分布式·kafka·rocketmq
宋发元11 天前
消息队列ActiveMQ、RabbitMQ、RocketMQ、Kafka对比分析和选型
消息队列·rabbitmq·rocketmq·activemq
橡果的笔记13 天前
5.借助RocketMQ实现批量消费存储设备上线次数
后端·数据分析·rocketmq