RocketMQ基础一

RocketMQ简介

  • RocketMQ 是阿里巴巴开源的分布式消息中间件,2016 年捐赠给 Apache 软件基金会,2017 年毕业成为 Apache 顶级项目。它使用 Java 编写,天然对 Java 生态友好:客户端 API、序列化、线程模型对 Java 工程师几乎零学习成本,源码也便于排查问题。
  • 4.x 是 RocketMQ 的经典架构版本:NameServer + Broker + Client 的扁平结构,没有任何第三方依赖(不需要 ZooKeeper),单机可支撑十万级 TPS。大量存量线上系统至今仍运行 4.x,理解它也是理解 5.x 的前提。
  • 核心特性:
    • 高吞吐、低延迟: 磁盘顺序写 + 内存映射(mmap)+ 页缓存(PageCache)+ 零拷贝,常态毫秒级投递延迟。
    • 亿级消息堆积: 消息全部落盘、索引与数据分离,堆积不降低吞吐(消费不追热点数据时几乎无性能衰减)
    • 功能完备: 事务消息、延时消息、顺序消息、消息轨迹、死信队列、消息查询(按 Key / 消息 ID)开箱即用。
    • 部署极简: NameServer 无状态、节点间零通信,集群扩缩容只需增减进程。
    • 客户端丰富: Java / C++ / Go / Python 等多语言客户端,Java 客户端最为成熟。

RocketMQ相关概念

  • RocketMQ架构上主要分为四部分:

    • Producer(消息生产者): 支持分布式集群方式部署。它会通过MQ的负载均衡模块选择相应的broker集群队列进行消息投递,投递的过程支持快速失败并且低延迟

    • Consumer(消息消费者): 支持分布式集群方式部署。存在pull、push两种消费模式消费消息,同时也支持集群方式和广播方式的消费。它提供实时消息订阅机制,可满足大多数场景需求

    • NameServer(路由注册中心): NameServer是一个简单的Topic路由注册中心,支持Broker的动态注册与发现。主要有两个功能:

      • Broker管理:NameServer接收并保存Broker集群的注册信息,用于作为路由信息的基本数据(比如:Broker与Topic的映射关系),并提供心跳检测机制,检查Broker是否处于存活状态
      • 路由信息管理:每个NameServer都会保存关于Broker集群的路由信息和用于客户端查询的队列信息
      • 注意:NameServer通常使用集群方式部署,各实例间不进行信息通讯。Broker启动时会向集群中的每一台NameServer注册自己的路由信息(包含ip地址、端口号、topic等)。因此,当某一个NameServr宕机后,Broker仍可向其它NameServer同步其路由信息;Producer、Consumer仍可通过NameServer动态感知Broker的路由信息
    • BrokerServer: Broker主要负责消息的存储、投递、查询以及服务高可用保证,为了实现这些功能,Broker包含以下几个重要子模块:

      • Remoting Module:整个Broker的实体,负责处理来自clients端的请求
      • Client Manager:负责管理客户端(Producer/Consumer)并并维护Consumer的Topic订阅信息
      • Store Service:提供方便简单的API接口用于查询或处理消息存储到磁盘
      • HA Service:高可用服务,提供Master Broker和Slave Broker之间的数据同步功能
      • Index Service:根据特定的Message key对投递到Broker的消息进行索引服务,以提供消息的快速查询

RocketMQ安装及启动

相关压缩包安装及配置

  • Step1: 进入RocketMQ官网下载(博主此处使用的是4.9.6版本)

    RocketMQ官网有两个包:

    • Source:java源码包,适合想读源码、调试源码、二次开发的人
    • Binary:java源码编译后可运行的二进制包,用于部署RocketMQ

    注意:博主此时均下载。Binary用于部署,Binary后期博主会来解读源码

  • Step2: 去jdk官网下载Linux版本的jdk1.8

  • Step3: 在Linux中利用下述命令分别创建java目录、rocketmq目录,然后将jdk的压缩包以及rocketmq的二进制包分别上传到对应的目录下

    sh 复制代码
    mkdir -p /usr/local/java
    mkdir -p /usr/local/rocketmq
  • Step4: 利用cd /usr/local/java进入到java目录下,然后执行tar -zxvf jdk-8u202-linux-x64.tar.gz命令解压jdk包

  • Step5: 利用cd /usr/local/rocketmq进入到rocketmq目录下,然后执行unzip rocketmq-all-4.9.6-bin-release.zip命令解压压缩包

    注意:若解压报错下述内容,则可通过wget https://mirrors.aliyun.com/apache/rocketmq/4.9.6/rocketmq-all-4.9.6-bin-release.zip命令下载指定版本当当前目录下,然后在解压

  • Step6: 安装完成后在对应目录下分别使用下述命令删除对应的包

    sh 复制代码
    rm -rf jdk-8u202-linux-x64.tar.gz
    rm -rf rocketmq-all-4.9.6-bin-release.zip
  • Step7: 利用vi /etc/profile命令进入对应文件,然后在文件末尾加上下述命令

    注意:profile是用来配置环境变量的文件

    sh 复制代码
    export JAVA_HOME=/usr/local/java/jdk1.8.0_202
    export JRE_HOME=/usr/local/java/jdk1.8.0_202/jre
    export ROCKETMQ_HOME=/usr/local/rocketmq/rocketmq-all-4.9.6-bin-release
    export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
    export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$ROCKETMQ_HOME/bin:$PATH:$HOME/bin
  • Step8: 执行source /etc/profile命令使配置生效,然后使用java、javac两个命令验证配置是否生效

RocketMQ目录内容详解

  • rocketmq的conf目录下有五个重要内容(如下图所示),分别为:

    • 2m-2s-async(双主双从 + 异步复制模板): Master 写完立即返回、Slave 后台同步(即使用异步方式进行主从之间的数据复制),性能高,吞吐量大,但Master 宕机瞬间可能丢失少量未同步消息
    • 2m-2s-sync(双主双从 + 同步复制模板): Master 等 Slave 也落盘成功才返回(即使用同步方式进行主从之间的数据复制),能够保证消息安全投递,不会丢失,但写入延迟略高,影响吞吐量
    • 2m-noslave(双主无从模板): 只有 Master 没有备份,性能最好、资源最省,
      • 缺点:会存在单点故障,读的性能没有前两种好,任一Master节点宕机则宕机Master节点上的消息暂时不可消费
    • dledger: 是基于 DLedger(Raft 协议)的多副本模板。由 Raft自动选主切主,解决传统主从架构 Master 宕机需人工切换的问题。
      • 注意:dledger是第三方的插件,在RocketMQ4.5之后为实现高可用性引入的
      • 解决的问题:2m-2s-async、2m-2s-sync、2m-noslave这三种官方提供的集群没办法实现高可用,在主节点宕机后并不会将某一个从节点升级为主节点(除非人工介入),而dledger就用来解决该问题
    • broker.conf: 默认的单机 Broker 配置模板,不带集群拓扑
  • 进入到2m-2s-async或2m-2s-sync目录下可看到两个主节点、两个从节点

单机部署

NameServer启动

  • Step1: 利用vi /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/runserver.sh命令进入到runserver文件中,更改nameServer所使用的JVM内存

    注意:RocketMQ默认的JVM内存为4G,由于博主是用来测试的,所以JVM内存配置小一点即可。若生产环境使用则根据实际情况配置大小

  • Step2: 利用下述命令静默启动nameServer

    • -n:说明启动的nameServer是在哪台服务器上的
    sh 复制代码
    nohup /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/mqnamesrv -n 192.168.204.128 &
  • Step3: 启动完成后执行cat nohup.out命令查看是否启动成功

Broker启动

  • Step1: 利用vi /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/runbroker.sh命令进入到broker文件中,更改broker所使用的JVM内存

    注意:由于博主是用来测试的,所以JVM内存配置小一点即可。若生产环境使用则根据实际情况配置大小

  • Step2: 利用 vi /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/conf/broker.conf进入broker.conf文件添加下述配置,开启自动创建topic功能

    sh 复制代码
    autoCreateTopicEnable=true
  • Step3: 利用下述命令静默启动nameServer

    • -n:Broker启动时指定要注册到的NameServer的地址
    sh 复制代码
    nohup /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/mqbroker -n 192.168.204.128:9876 &
  • Step4: 启动完成后执行cat nohup.out命令查看是否启动成功

RocketMQ消息发送\消费验证

  • Step1: 利用vi /etc/profile命令编辑profile文件,添加下述配置

    原因:在发送/接收消息之前,告知客户端NameServer的位置,让tools工具中的生产者和消费者程序读取该变量实现消息的生产和消费

    sh 复制代码
    export NAMESRV_ADDR=192.168.204.128:9876
  • Step2: 执行source /etc/profile命令使配置生效

  • Step3: 使用bin/tools.sh工具验证生产者消息发送(默认会发送1000条消息),具体命令如下:

    sh 复制代码
    /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/tools.sh org.apache.rocketmq.example.quickstart.Producer
  • Step4: 使用bin/tools.sh工具验证生产者消息发送(默认会发送1000条消息),具体命令如下:

    sh 复制代码
    /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer

RocketMQ关闭

  • 依次利用下述命令关闭Broker、NameServer

    sh 复制代码
    /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/mqshutdown broker
    
    /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/mqshutdown namesrv

集群部署

  • 为了追求更好的性能,RocketMQ的最佳实践方式都是在集群模式下完成的。RocketMQ官方提供了三种集群搭建方式(具体可见 RocketMQ目录内容详解 这一部分内容):

    • 2主2从异步通信方式

      • 使用conf/2m-2s-async文件夹内的配置文件做集群配置
    • 2主2从同步通信方式

      • 使用conf/2m-2s-sync文件夹内的配置文件做集群配置
    • 2主无从方式

      • 使用conf/2m-noslave文件夹内的配置文件做集群配置
    • Dleger高可用集群

      • 上述三种官方提供的集群没办法实现高可用时使用(即:在master节点宕机后,slave节点没办法自动被选举为新的master,必须借助人工实现选举)

搭建主从异步集群

在搭建主从异步集群前必须准备三台Linux服务器,三台Linux服务器中nameServer和broker之间的关系如下:

注意:

  • 服务器2、3中分别创建了两个主节点,以及这两个主节点对应的从节点
  • 同一主从节点不得在同一个服务器上
    • 原因:若某一台服务器宕机,另一台服务器仍存在对应的相关节点,保持可用性
服务器 服务器IP NameServer broker节点部署
服务器1 192.168.204.128 192.168.204.128:9876
服务器2 192.168.204.129 192.168.204.129:9876 broker-a(master)、broker-b-s(slave)
服务器3 192.168.204.130 192.168.204.130:9876 broker-b(master)、broker-a-s(slave)
  • Step1: 创建三台Linux服务器,创建完成后启动

    • 注意:博主在进行单击部署时已有一台。因此,在创建两台即可。具体步骤可详见Linux(完整知识点汇总)这一部分内容
  • Step2: 依次在DemoTwo、DemoThree中按照相关压缩包安装及配置这一小节执行一遍

NameServer启动

注意:该小节与 单机部署->NameServer启动 步骤一致,此处不再演示

服务器2的Broker启动

  • Step1: 在 服务器2 中利用vi /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/conf/2m-2s-async/broker-a.properties命令编辑broker-a.properties配置文件,新增内容如下:

    主节点broker-a需要在broker-a.properties配置文件中配置

    properties 复制代码
    # 所属集群名称
    brokerClusterName=DefaultCluster
    # broker名字
    brokerName=broker-a
    # broker所在的服务器的ip(注意:需改为自己当前服务器的ip地址)
    brokerIP1=192.168.204.129
    # broker的id,0代表master主节点,>0代表slave从节点
    brokerId=0
    # 删除文件时间点,默认在凌晨4点
    deleteWhen=04
    # 文件保留时间为48小时
    fileReservedTime=48
    # broker的角色为master(由于当前搭建的是异步集群,所以角色设置为ASYNC_MASTER)
    brokerRole=ASYNC_MASTER
    # 刷盘方式(由于当前是异步集群,所以配置为异步刷盘)
    flushDiskType=ASYNC_FLUSH
    # 名称服务器的地址列表namesrvAddr(即:NameServer集群IP地址)
    namesrvAddr=192.168.204.128:9876;192.168.204.129:9876;192.168.204.130:9876
    # 在发送消息自动创建不存在的topic时,指定默认创建的队列数
    defaultTopicQueueNums=4
    # 是否允许Broker自动创建Topic(建议线下开启,线上关闭)
    autoCreateTopicEnable=true
    # 是否允许Broker自动创建订阅组,建议线下开启,线上关闭
    autoCreateSubscriptionGroup=true
    # broker对外服务的监听端口(同一台服务器上多个 broker 端口不能冲突)
    listenPort=10911
    # abort文件存储路径(注意:同一服务器上主节点和从节点的abort文件存储路径要分开,否则集群会启动失败)
    abortFile=/usr/local/rocketmq/store/abort
    # 消息存储路径(注意:同一服务器上主节点和从节点的消息存储路径要分开,否则集群会启动失败)
    storePathRootDir=/usr/local/rocketmq/store
    # commitLog存储路径(注意:同一服务器上主节点和从节点的commitLog存储路径要分开,否则集群会启动失败)
    storePathCommitLog=/usr/local/rocketmq/store/commitlog
    # 消息队列存储路径(注意:同一服务器上主节点和从节点的消息队列存储路径要分开,否则集群会启动失败)
    storePathConsumeQueue=/usr/local/rocketmq/store/consumequeue
    # 消息索引存储路径(注意:同一服务器上主节点和从节点的消息索引存储路径要分开,否则集群会启动失败)
    storePathIndex=/usr/local/rocketmq/store/index
    # checkpoint文件存储路径(注意:同一服务器上主节点和从节点的checkpoint文件存储路径要分开,否则集群会启动失败)
    storeCheckpoint=/usr/local/rocketmq/store/checkpoint
    # 限制的消息大小
    maxMessageSize=65536
    # commitLog每个文件的大小默认1G
    mapedFileSizeCommitLog=1073741824
    # ConsumeQueue每个文件默认存30w条,根据业务情况调整
    mapedFileSizeConsumeQueue=300000
  • Step2: 在 服务器2 中利用vi /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/conf/2m-2s-async/broker-b-s.properties命令编辑broker-b-s.properties配置文件,新增内容如下:

    由于该从节点并不是当前服务器中broker-a主节点的从节点。因此,从节点需要在broker-b-s.properties配置文件中配置,而不是在broker-a-s.properties中配置

    properties 复制代码
    # 所属集群名称
    brokerClusterName=DefaultCluster
    # broker名字
    brokerName=broker-b
    # broker所在的服务器的ip(注意:需改为自己当前服务器的ip地址)
    brokerIP1=192.168.204.129
    # broker的id,0代表master主节点,>0代表slave从节点
    brokerId=1
    # 删除文件时间点,默认在凌晨4点
    deleteWhen=04
    # 文件保留时间为48小时
    fileReservedTime=48
    # broker的角色为slave(由于当前搭建的是异步集群,所以角色设置为SLAVE)
    brokerRole=SLAVE
    # 刷盘方式(由于当前是异步集群,所以配置为异步刷盘)
    flushDiskType=ASYNC_FLUSH
    # 名称服务器的地址列表(即:NameServer集群IP地址)
    namesrvAddr=192.168.204.128:9876;192.168.204.129:9876;192.168.204.130:9876
    # 在发送消息自动创建不存在的topic时,指定默认创建的队列数
    defaultTopicQueueNums=4
    # 是否允许Broker自动创建Topic(建议线下开启,线上关闭)
    autoCreateTopicEnable=true
    # 是否允许Broker自动创建订阅组,建议线下开启,线上关闭
    autoCreateSubscriptionGroup=true
    # broker对外服务的监听端口(同一台服务器上多个 broker 端口不能冲突)
    listenPort=11011
    # abort文件存储路径(注意:同一服务器上主节点和从节点的abort文件存储路径要分开,否则集群会启动失败)
    abortFile=/usr/local/rocketmq/store-slave/abort
    # 消息存储路径(注意:同一服务器上主节点和从节点的消息存储路径要分开,否则集群会启动失败)
    storePathRootDir=/usr/local/rocketmq/store-slave
    # commitLog存储路径(注意:同一服务器上主节点和从节点的commitLog存储路径要分开,否则集群会启动失败)
    storePathCommitLog=/usr/local/rocketmq/store-slave/commitlog
    # 消息队列存储路径(注意:同一服务器上主节点和从节点的消息队列存储路径要分开,否则集群会启动失败)
    storePathConsumeQueue=/usr/local/rocketmq/store-slave/consumequeue
    # 消息索引存储路径(注意:同一服务器上主节点和从节点的消息索引存储路径要分开,否则集群会启动失败)
    storePathIndex=/usr/local/rocketmq/store-slave/index
    # checkpoint文件存储路径(注意:同一服务器上主节点和从节点的checkpoint文件存储路径要分开,否则集群会启动失败)
    storeCheckpoint=/usr/local/rocketmq/store-slave/checkpoint
    # 限制的消息大小
    maxMessageSize=65536
  • Step3: 利用vi /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/runbroker.sh命令进入到 服务器2 的broker文件中,更改broker所使用的JVM内存

    注意:由于博主是用来测试的,所以JVM内存配置小一点即可。若生产环境使用则根据实际情况配置大小

  • Step4: 利用下述命令依次静默启动两个broker

    • -c:指定对应的配置文件,使启动的集群满足配置内容
    sh 复制代码
    nohup /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/mqbroker -c /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/conf/2m-2s-async/broker-a.properties &
    sh 复制代码
    nohup /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/mqbroker -c /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/conf/2m-2s-async/broker-b-s.properties &

    注意:博主图示方式中是将上述两个命令合并到一起来启动,实测会出问题导致只启动其中一个。因此,最好上述两个命令依次启动,并使用cat nohup.out命令查看日志是否真正启动成功

  • Step5: 利用jps命令检查当前服务器是否存在两个broker,一个nameServer程序(目的:进一步验证是否启动成功)

服务器3的Broker启动

  • Step1: 在 服务器3 中利用vi /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/conf/2m-2s-async/broker-b.properties命令编辑broker-a.properties配置文件,新增内容如下:

    主节点broker-b需要在broker-a.properties配置文件中配置

    properties 复制代码
    # 所属集群名称
    brokerClusterName=DefaultCluster
    # broker名字
    brokerName=broker-b
    # broker所在的服务器的ip(注意:需改为自己当前服务器的ip地址)
    brokerIP1=192.168.204.130
    # broker的id,0代表master主节点,>0代表slave从节点
    brokerId=0
    # 删除文件时间点,默认在凌晨4点
    deleteWhen=04
    # 文件保留时间为48小时
    fileReservedTime=48
    # broker的角色为master(由于当前搭建的是异步集群,所以角色设置为ASYNC_MASTER)
    brokerRole=ASYNC_MASTER
    # 刷盘方式(由于当前是异步集群,所以配置为异步刷盘)
    flushDiskType=ASYNC_FLUSH
    # 名称服务器的地址列表(即:NameServer集群IP地址)
    namesrvAddr=192.168.204.128:9876;192.168.204.129:9876;192.168.204.130:9876
    # 在发送消息自动创建不存在的topic时,指定默认创建的队列数
    defaultTopicQueueNums=4
    # 是否允许Broker自动创建Topic(建议线下开启,线上关闭)
    autoCreateTopicEnable=true
    # 是否允许Broker自动创建订阅组,建议线下开启,线上关闭
    autoCreateSubscriptionGroup=true
    # broker对外服务的监听端口(同一台服务器上多个 broker 端口不能冲突)
    listenPort=10911
    # abort文件存储路径(注意:同一服务器上主节点和从节点的abort文件存储路径要分开,否则集群会启动失败)
    abortFile=/usr/local/rocketmq/store/abort
    # 消息存储路径(注意:同一服务器上主节点和从节点的消息存储路径要分开,否则集群会启动失败)
    storePathRootDir=/usr/local/rocketmq/store
    # commitLog存储路径(注意:同一服务器上主节点和从节点的commitLog存储路径要分开,否则集群会启动失败)
    storePathCommitLog=/usr/local/rocketmq/store/commitlog
    # 消息队列存储路径(注意:同一服务器上主节点和从节点的消息队列存储路径要分开,否则集群会启动失败)
    storePathConsumeQueue=/usr/local/rocketmq/store/consumequeue
    # 消息索引存储路径(注意:同一服务器上主节点和从节点的消息索引存储路径要分开,否则集群会启动失败)
    storePathIndex=/usr/local/rocketmq/store/index
    # checkpoint文件存储路径(注意:同一服务器上主节点和从节点的checkpoint文件存储路径要分开,否则集群会启动失败)
    storeCheckpoint=/usr/local/rocketmq/store/checkpoint
    # 限制的消息大小
    maxMessageSize=65536
    # commitLog每个文件的大小默认1G
    mapedFileSizeCommitLog=1073741824
    # ConsumeQueue每个文件默认存30w条,根据业务情况调整
    mapedFileSizeConsumeQueue=300000
  • Step2: 在 服务器3 中利用vi /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/conf/2m-2s-async/broker-a-s.properties命令编辑broker-a-s.properties配置文件,新增内容如下:

    由于该从节点并不是当前服务器中broker-b主节点的从节点。因此,从节点需要在broker-a-s.properties配置文件中配置,而不是在broker-b-s.properties中配置

    注意:

    • 同一服务器上不可能存在同一个broker的主从节点。因此,当前服务器上的broker节点(主/从)的对外服务的监听端口要与其它服务器上对应的broker节点(从/主)的监听端口要一致,否则无法搭建主从异步集群
    properties 复制代码
    # 所属集群名称
    brokerClusterName=DefaultCluster
    # broker名字
    brokerName=broker-a
    # broker所在的服务器的ip(注意:需改为自己当前服务器的ip地址)
    brokerIP1=192.168.204.130
    # broker的id,0代表master主节点,>0代表slave从节点
    brokerId=1
    # 删除文件时间点,默认在凌晨4点
    deleteWhen=04
    # 文件保留时间为48小时
    fileReservedTime=48
    # broker的角色为slave(由于当前搭建的是异步集群,所以角色设置为SLAVE)
    brokerRole=SLAVE
    # 刷盘方式(由于当前是异步集群,所以配置为异步刷盘)
    flushDiskType=ASYNC_FLUSH
    # 名称服务器的地址列表(即:NameServer集群IP地址)
    namesrvAddr=192.168.204.128:9876;192.168.204.129:9876;192.168.204.130:9876
    # 在发送消息自动创建不存在的topic时,指定默认创建的队列数
    defaultTopicQueueNums=4
    # 是否允许Broker自动创建Topic(建议线下开启,线上关闭)
    autoCreateTopicEnable=true
    # 是否允许Broker自动创建订阅组,建议线下开启,线上关闭
    autoCreateSubscriptionGroup=true
    # broker对外服务的监听端口(同一台服务器上多个 broker 端口不能冲突)
    listenPort=11011
    # abort文件存储路径(注意:同一服务器上主节点和从节点的abort文件存储路径要分开,否则集群会启动失败)
    abortFile=/usr/local/rocketmq/store-slave/abort
    # 消息存储路径(注意:同一服务器上主节点和从节点的消息存储路径要分开,否则集群会启动失败)
    storePathRootDir=/usr/local/rocketmq/store-slave
    # commitLog存储路径(注意:同一服务器上主节点和从节点的commitLog存储路径要分开,否则集群会启动失败)
    storePathCommitLog=/usr/local/rocketmq/store-slave/commitlog
    # 消息队列存储路径(注意:同一服务器上主节点和从节点的消息队列存储路径要分开,否则集群会启动失败)
    storePathConsumeQueue=/usr/local/rocketmq/store-slave/consumequeue
    # 消息索引存储路径(注意:同一服务器上主节点和从节点的消息索引存储路径要分开,否则集群会启动失败)
    storePathIndex=/usr/local/rocketmq/store-slave/index
    # checkpoint文件存储路径(注意:同一服务器上主节点和从节点的checkpoint文件存储路径要分开,否则集群会启动失败)
    storeCheckpoint=/usr/local/rocketmq/store-slave/checkpoint
    # 限制的消息大小
    maxMessageSize=65536
  • Step3: 利用vi /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/runbroker.sh命令进入到 服务器3 的broker文件中,更改broker所使用的JVM内存

    注意:由于博主是用来测试的,所以JVM内存配置小一点即可。若生产环境使用则根据实际情况配置大小

  • Step4: 利用下述命令静默启动nameServer

    • -c:指定对应的配置文件,使启动的集群满足配置内容
    sh 复制代码
    nohup /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/mqbroker -c /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/conf/2m-2s-async/broker-b.properties &
    复制代码
    nohup /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/mqbroker -c /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/conf/2m-2s-async/broker-a-s.properties &

    注意:博主图示方式中是将上述两个命令合并到一起来启动,实测会出问题导致只启动其中一个。因此,最好上述两个命令依次启动,并使用cat nohup.out命令查看日志是否真正启动成功

  • Step5: 利用jps命令检查当前服务器是否存在两个broker,一个nameServer程序(目的:进一步验证是否启动成功)

服务器Broker配置类属性注意事项

属性 定义 注意 备注
brokerClusterName 所属集群名称 同属一个集群的集群名称必须一致
brokerName broker名称 同一broker的主从节点的broker名字必须一致
brokerId broker的id 0代表master主节点,>0代表slave从节点 集群中主从配对靠的是 brokerName 相同 + brokerId 区分
brokerRole broker的角色 角色名固定枚举,只有三个合法值:ASYNC_MASTER、SYNC_MASTER、SLAVE 在RocketMQ5.x后新增合法值:ASYNC_SLAVE
listenPort broker对外服务的监听端口 同一台服务器上多个 broker 端口不能冲突
namesrvAddr 名称服务器的地址列表(即:NameServer集群IP地址)

验证集群是否正常工作

为避免NameServe、Broker仅运行成功但不可正常工作。因此,使用RocketMQ集群提供的tools工具来验证集群是否可正常工作

  • Step1: 在服务器2上利用vi /etc/profile命令编辑profile文件,添加下述配置

    原因:在发送/接收消息之前,告知客户端NameServer的位置,让tools工具中的生产者和消费者程序读取该变量实现消息的生产和消费

    sh 复制代码
    export NAMESRV_ADDR='192.168.204.128:9876;192.168.204.129:9876;192.168.204.130:9876'
  • Step2: 执行source /etc/profile命令使配置生效

  • Step3: 在服务器2使用bin/tools.sh工具验证生产者消息发送(默认会发送1000条消息),具体命令如下:

    sh 复制代码
    /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/tools.sh org.apache.rocketmq.example.quickstart.Producer
  • Step3: 在服务器2使用bin/tools.sh工具验证生产者消息发送(默认会发送1000条消息),具体命令如下:

    sh 复制代码
    /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer

注意:正常情况下可成功发送并消费消息。博主此处不再上传演示图

集群关闭

  • 在对应服务器中依次利用下述命令关闭Broker、NameServer即可

    sh 复制代码
    /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/mqshutdown broker
    
    /usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/mqshutdown namesrv

mqadmin管理工具

RocketMQ的bin目录下提供了命令工具用于管理topic、broker、集群、消息等。

mqadmin常见命令-创建topic

命令:updateTopic

示例:创建名为myTopic1的topic,且指定所属集群的名称为DefaultCluster

sh 复制代码
/usr/local/rocketmq/rocketmq-all-4.9.6-bin-release/bin/mqadmin updateTopic -n 192.168.204.129:9876 -c DefaultCluster -t myTopic1
参数 是否必填 备注
-b 若-c为空,则该参数必填 broker地址,表示topic建在该broker上(并不是集群中的每个broker都会创建指定topic)
-c 若-b为空,则该参数必填 cluster名称,表示topic建在该集群(即:集群中的每个broker上都有;集群可通过clusterList查询)
-h 否 打印帮助
-n 是 nameServer服务地址列表,格式:ip:port;ip:port
-p 否 指定新topic的权限限制(W|R|WR)
-r 否 可读队列数(默认为8)
-w 否 可写队列数(默认为8)
-t 是 opic名称(名称只能使用字符^[a-zA-Z0-9_-+$)

mqadmin常见命令-删除topic

命令deleteTopic

参数 是否必填 备注
-c 是 cluster名称,表示删除某个集群下的某个topic(集群可通过clusterList查询)
-h 否 打印帮助
-n 是 nameServer服务地址列表,格式:ip:port;ip:port
-t 是 opic名称(名称只能使用字符^[a-zA-Z0-9_-+$)

mqadmin常见命令-创建/修改订阅组

命令updateSubGroup

参数 是否必填 备注
-b 若-c为空,则该参数必填 broker地址,表示订阅组建在该broker
-c 若-b为空,则该参数必填 cluster名称,表示topic建在该集群(集群可通过clusterList查询)
-d 否 是否允许广播方式消费
-g 是 订阅组名
-i 否 从哪个broker开始消费
-m 否 是否容许从队列的最小位置开始消费,默认为false
-q 否 消费失败的消息放到一个重试队列,每个订阅组配置几个重试队列
-r 否 重试消费的最大次数,超过则投递到死信队列,此时不投递并报警
-s 否 消费功能是否开启
-w 否 发现消息堆积后,将Consumer的消费请求重定向到另一台Slave机器
-h 否 打印帮助
-n 是 nameServer服务地址列表,格式:ip:port;ip:port

mqadmin常见命令-删除订阅组配置

命令deleteSubGroup

参数 是否必填 备注
-b 若-c为空,则该参数必填 broker地址,表示订阅组建在该broker
-c 若-b为空,则该参数必填 cluster名称,表示topic建在该集群(集群可通过clusterList查询)
-g 是 订阅组名
-h 否 打印帮助
-n 是 nameServer服务地址列表,格式:ip:port;ip:port

mqadmin常见命令-更新Broker配置文件

命令updateBrokerConfig

参数 是否必填 备注
-b 若-c为空,则该参数必填 broker地址,表示订阅组建在该broker
-c 若-b为空,则该参数必填 cluster名称,表示topic建在该集群(集群可通过clusterList查询)
-k 是 key值
-v 否 value值
-h 否 打印帮助
-n 是 nameServer服务地址列表,格式:ip:port;ip:port

mqadmin常见命令-查看topic列表信息

命令topicList

参数 是否必填 备注
-h 否 打印帮助
-n 是 nameServer服务地址列表,格式:ip:port;ip:port

mqadmin常见命令-查看topic路由信息

命令topicRoute

参数 是否必填 备注
-t 是 topic名称
-h 否 打印帮助
-n 是 nameServer服务地址列表,格式:ip:port;ip:port

mqadmin常见命令-查看topic统计信息

命令topicStats

参数 是否必填 备注
-t 是 topic名称
-h 否 打印帮助
-n 是 nameServer服务地址列表,格式:ip:port;ip:port

mqadmin常见命令-根据消息ID查询消息

命令queryMsgById

参数 是否必填 备注
-i 是 消息ID
-h 否 打印帮助
-n 是 nameServer服务地址列表,格式:ip:port;ip:port

mqadmin常见命令-根据消息key查询消息

命令queryMsgByKey

参数 是否必填 备注
-f 否 被查询消息的截止时间
-k 是 msgKey
-t 是 topic名称
-h 否 打印帮助
-n 是 nameServer服务地址列表,格式:ip:port;ip:port

mqadmin常见命令-根据Offset查询消息

命令queryMsgByOffset

参数 是否必填 备注
-b 是 Broker名称,表示订阅组建在该Broker(注意:此处填写的是Broker名称,不是地址,broker名称可在clusterList查询)
-i 是 query队列id
-o 是 offset值
-t 是 topic名称
-h 否 打印帮助
-n 是 nameServer服务地址列表,格式:ip:port;ip:port

mqadmin常见命令-查询Producer的网络连接

命令producerConnection

参数 是否必填 备注
-g 是 生产者所属组名
-t 是 topic名称
-h 否 打印帮助
-n 是 nameServer服务地址列表,格式:ip:port;ip:port

mqadmin常见命令-查询Consumer的网络连接

命令consumerConnection

参数 是否必填 备注
-g 是 消费者所属组名
-h 否 打印帮助
-n 是 nameServer服务地址列表,格式:ip:port;ip:port

mqadmin常见命令-查询订阅组消费状态

命令consumerProgress

参数 是否必填 备注
-g 是 消费者所属组名
-h 否 打印帮助
-n 是 nameServer服务地址列表,格式:ip:port;ip:port

mqadmin常见命令-查看集群消息

命令clusterList

参数 是否必填 备注
-m 否 打印更多信息
-h 否 打印帮助
-n 是 nameServer服务地址列表,格式:ip:port;ip:port

可视化管理控制平台安装及使用

注意:博主将可视化管理控制平台安装到了服务器1上

前置步骤

可视化管理控制平台安装前需要保证Linux中已安装Jdk、Maven、已启动nameServer、Broker

由于博主除了Maven外,其余均已完成。因此,需要先安装Maven

  • Step1: 进入Maven官网下载对应版本的Maven(博主版本为3.9.16)

  • Step2: 在Linux中利用mkdir -p /usr/local/maven命令创建maven目录,然后将maven的二进制包上传到该目录下

  • Step3: 利用cd /usr/local/maven进入到maven目录下,然后执行tar -zxvf apache-maven-3.9.16-bin.tar.gz命令解压maven包

  • Step4: 利用vi /etc/profile命令来配置maven环境变量,在profile文件中新增下述配置

    sh 复制代码
    export MAVEN_HOME=/usr/local/maven/apache-maven-3.9.16
    export PATH=$JAVA_HOME/bin:$MAVEN_HOME/bin:$PATH
  • Step5: 执行source /etc/profile命令使配置生效,然后使用mvn -v命令验证配置是否生效

可视化管理控制平台安装

注意:可视化管理控制平台安装也可去官方管理控制平台下载zip包将其解压到本地,然后用idea打开,修改完application.yml后打包生成jar包,并将jar包上传至Linux,通过java -jar rocketmq-dashboard-2.0.0.jar命令运行。

博主此处仅演示全程在Linux中是如何操作的,在windows平台利用idea的实现可自行尝试

  • Step1: 进入官方管理控制平台下载zip包

    注意:

    • 博主此处下载的是2.0.0版本
      • 原因:2.0.0版本之后要求jdk版本在17及其以上,而本次案例中博主使用的是jdk1.8构建的RocketMQ
    • 在实测过程中由于2.0.0版本中对应的ocketMQ依赖版本为5.1.0(博主使用的为RocketMQ4.9.6)。因此,在操作可视化管理控制平台过程中可能会无法操作甚至操作失败。
      • 建议:为避免遇到与博主一样的问题。建议使用RocketMQ4.9.0版本,可视化管理控制平台使用1.0.0版本
      • 原因:可视化管理控制平台1.0.0版本中使用的RocketMQ版本为4.9.0
  • Step2: 在Linux中利用mkdir -p /usr/local/rocketmq/rocketmq-dashboard命令创建rocketmq-dashboard目录,然后将rocketmq-dashboard的压缩包上传到该目录下

  • Step3: 利用cd /usr/local/rocketmq/rocketmq-dashboard进入到rocketmq-dashboard目录下,然后执行unzip rocketmq-dashboard-rocketmq-dashboard-2.0.0.zip命令解压rocketmq-dashboard包

  • Step4: 利用vi /usr/local/rocketmq/rocketmq-dashboard/rocketmq-dashboard-rocketmq-dashboard-2.0.0/src/main/resources/application.yml命令在application.yml中更新rocketmq.config.namesrvAddrs配置的ip地址为当前集群中NameServer的ip地址

  • Step5: 利用cd /usr/local/rocketmq/rocketmq-dashboard/rocketmq-dashboard-rocketmq-dashboard-2.0.0进入到rocketmq-dashboard项目目录下,双击打开pom文件(如图一所示),然后在pom文件中为yarn配置国内yarn源(如图二所示)

    xml 复制代码
    <configuration>
        <nodeVersion>v16.2.0</nodeVersion>
        <yarnVersion>v1.22.10</yarnVersion>
        <nodeDownloadRoot>https://cdn.npmmirror.com/binaries/node/</nodeDownloadRoot>
        <yarnDownloadRoot>https://repo.huaweicloud.com/yarn/</yarnDownloadRoot>
    </configuration>
  • Step6: 利用cd /usr/local/rocketmq/rocketmq-dashboard/rocketmq-dashboard-rocketmq-dashboard-2.0.0进入到rocketmq-dashboard项目目录下,然后利用mvn clean package -Dmaven.test.skip=true命令对该rocketmq-dashboard项目进行打包

    注意:打包完成后可看到target目录下有一个jar包(如图所示)

  • Step7: 利用 cd /usr/local/rocketmq/rocketmq-dashboard/rocketmq-dashboard-rocketmq-dashboard-2.0.0/target 进入到target目录,然后利用java -jar rocketmq-dashboard-2.0.0.jar启动项目。如图所示即为启动成功

  • Step8: 在浏览器中输入IP地址:8080即可访问可视化管理控制平台(如图所示)

    注意:博主在服务器1上安装的可视化管理控制平台。因为地址为:http://192.168.204.128:8080/

RocketMQ快速入门

示例:生产者向消息队列发送"HelloWorld!!!",然后由消费者从消息队列接收到消息并在控制台输出

注意:

前置步骤

  • 在父pom文件中新增rocketmq-client依赖

    注意:该依赖版本必须与RocketMQ部署的版本一致,博主部署时使用的是4.9.6。因此,rocketmq-client依赖依赖版本为4.9.6

    xml 复制代码
    <!--RocketMQ相关依赖-->
    <dependency>
        <groupId>org.apache.rocketmq</groupId>
        <artifactId>rocketmq-client</artifactId>
        <version>4.9.6</version>
    </dependency>

    完整父pom文件如下:

    xml 复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>at.guigu</groupId>
        <artifactId>RocketMQDemo</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>pom</packaging>
        <modules>
            <module>consumer</module>
            <module>publisher</module>
        </modules>
    
        <properties>
            <maven.compiler.source>21</maven.compiler.source>
            <maven.compiler.target>21</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <spring-boot.version>3.0.7</spring-boot.version>
            <spring-cloud.version>2022.0.3</spring-cloud.version>
            <spring-cloud-alibaba.version>2022.0.0.0-RC2</spring-cloud-alibaba.version>
            <hutool-all.version>5.8.25</hutool-all.version>
        </properties>
    
        <!--5 配置公共依赖-->
        <dependencies>
            <!--启动类相关依赖:SpringBoot依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--RocketMQ相关依赖-->
            <dependency>
                <groupId>org.apache.rocketmq</groupId>
                <artifactId>rocketmq-client</artifactId>
                <version>4.9.6</version>
            </dependency>
    
            <!--测试类相关依赖:spring-boot-starter-test-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <!--添加Junit单元测试依赖-->
            <dependency >
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <scope>test</scope>
            </dependency>
            <!--lombok依赖-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>
            <!--hutool坐标-->
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>${hutool-all.version}</version>
            </dependency>
    
        </dependencies>
    
        <!--6 配置可选依赖-->
        <dependencyManagement>
            <dependencies>
                <!-- 覆盖SpringBoot默认的lombok 1.18.26(不支持JDK 21编译),须在import之前声明才生效 -->
                <dependency>
                    <groupId>org.projectlombok</groupId>
                    <artifactId>lombok</artifactId>
                    <version>1.18.36</version>
                </dependency>
                <!-- springboot的依赖-->
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>${spring-boot.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <!-- springcloud依赖-->
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <!--spring-cloud-alibaba-->
                <dependency>
                    <groupId>com.alibaba.cloud</groupId>
                    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                    <version>${spring-cloud-alibaba.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
    
        <build>
            <!--7 配置插件-->
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>

生产者模块步骤

  • Step1: 在生产者模块(即publisher模块)中创建测试类RocketMQPubTest,测试代码如下:

    java 复制代码
    package at.guigu;
    
    import org.apache.rocketmq.client.producer.DefaultMQProducer;
    import org.apache.rocketmq.client.producer.SendResult;
    import org.apache.rocketmq.common.message.Message;
    import org.junit.jupiter.api.Test;
    import org.springframework.boot.test.context.SpringBootTest;
    import java.nio.charset.StandardCharsets;
    
    @SpringBootTest
    public class RocketMQPubTest {
    
        @Test
        void pubTest() throws Exception {
            // Step1:创建生产者并指定生产者组
            DefaultMQProducer producer = new DefaultMQProducer("my-producer-group1");
            // Step2:指定nameServer地址(集群中任意一个nameServer的ip地址即可)
            producer.setNamesrvAddr("192.168.204.128:9876");
            // Step3:启动生产者
            producer.start();
            for (int i = 0; i < 10; i++) {
                // Step4:消息创建---注意:Message所在包为org.apache.rocketmq.common.message.Message
                Message msg = new Message("MyTopic1", "TagA", ("HelloWorld!!! " + i).getBytes(StandardCharsets.UTF_8));
                // Step5:(同步)消息发送
                SendResult result = producer.send(msg);
                System.out.println(result); // 打印发送结果
            }
            // Step6:关闭生产者
            producer.shutdown();
        }
    }
  • Step2: 运行该测试类,可看到如图所示内容

  • Step3: 进入到 可视化管理控制平台->消息 界面,选择指定的Topic即可看到发送的10条消息

消费者模块步骤

  • Step1: 在生产者模块(即publisher模块)中创建可单独启动的消费者类BaseConsumer,测试代码如下:

    注意:由于当前还未springboot整合rocketmq。因此,博主此处创建一个不依赖消费者模块启动类的消费者类来实现消费(即该类可单独执行,不用启动消费者模块启动类)

    java 复制代码
    package at.guigu.consumer;
    
    import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
    import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
    import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
    import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
    import org.apache.rocketmq.client.exception.MQClientException;
    import org.apache.rocketmq.common.message.MessageExt;
    import java.util.List;
    
    public class BaseConsumer {
        public static void main(String[] args) throws MQClientException {
            // Step1:创建消费者并指定消费者组
            DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("my-producer-group1");
            // Step2:指定nameServer地址(集群中任意一个nameServer的ip地址即可)
            consumer.setNamesrvAddr("192.168.204.128:9876");
            // Step3:消费者订阅对应的Topic,且过滤出tags为"TagA"的消息进行消费
            // 注意:若消费当前订阅的topic下的所有消息,则参数二改为"*"即可
            consumer.subscribe("MyTopic1", "TagA");
            // Step4:创建一个消息监听器,当Broker将消息push过来时调用,以实现消息消费
            consumer.registerMessageListener(new MessageListenerConcurrently() {
                /**
                 *
                 * @param msgs broker推过来的消息都在该列表中
                 * @param consumeConcurrentlyContext 上下文对象
                 * @return
                 */
                @Override
                public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
                    try {
                        // 具体消费逻辑
                        msgs.forEach(msg -> {
                            System.out.println("收到的消息:" + msg);
                        });
                    } catch (Exception e) {
                        // 若消费失败则返回RECONSUME_LATER,代表后续会重新消费
                        return ConsumeConcurrentlyStatus.RECONSUME_LATER;
                    }
                    // 若消费成功则返回CONSUME_SUCCESS
                    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                }
            });
            // Step5:启动消费者
            consumer.start();
            System.out.println("consumer running...");
        }
    }
  • Step2: 启动消费者类BaseConsumer,控制台输入如图所示:

    由图可知,消息为字节码数组。因此,若想要获取消息内容则需解码字节码数组:

    java 复制代码
    package at.guigu.consumer;
    
    import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
    import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
    import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
    import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
    import org.apache.rocketmq.client.exception.MQClientException;
    import org.apache.rocketmq.common.message.MessageExt;
    
    import java.nio.charset.StandardCharsets;
    import java.util.List;
    
    public class BaseConsumer {
        public static void main(String[] args) throws MQClientException {
            // Step1:创建消费者并指定消费者组
            DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("my-producer-group1");
            // Step2:指定nameServer地址(集群中任意一个nameServer的ip地址即可)
            consumer.setNamesrvAddr("192.168.204.128:9876");
            // Step3:消费者订阅对应的Topic,且过滤出tags为"TagA"的消息进行消费
            // 注意:若消费当前订阅的topic下的所有消息,则参数二改为"*"即可
            consumer.subscribe("MyTopic1", "TagA");
            // Step4:创建一个消息监听器,当Broker将消息push过来时调用,以实现消息消费
            consumer.registerMessageListener(new MessageListenerConcurrently() {
                /**
                 *
                 * @param msgs broker推过来的消息都在该列表中
                 * @param consumeConcurrentlyContext 上下文对象
                 * @return
                 */
                @Override
                public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
                    try {
                        // 具体消费逻辑
                        msgs.forEach(msg -> {
                            // 将获取到的字节码数组解码后输出
                            System.out.println("收到的消息:" + new String(msg.getBody(), StandardCharsets.UTF_8));
                        });
                    } catch (Exception e) {
                        // 若消费失败则返回RECONSUME_LATER,代表后续会重新消费
                        return ConsumeConcurrentlyStatus.RECONSUME_LATER;
                    }
                    // 若消费成功则返回CONSUME_SUCCESS
                    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                }
            });
            // Step5:启动消费者
            consumer.start();
            System.out.println("consumer running...");
        }
    }

    此时输出如下图所示:

相关推荐
蚂蚁背大象1 天前
RocketMQ-Rust 1.0.0 发布:用 Rust 做消息队列,这次有哪些变化?
rust·开源·rocketmq
此时不提桶,更待何时1 天前
06-08-B-RocketMQ面试与生产事故实战
面试·rocketmq
醉颜凉2 天前
Kafka 与 RabbitMQ/RocketMQ 选型对比:场景匹配、性能基准与迁移成本
kafka·消息队列·rabbitmq·rocketmq·中间件选型
此时不提桶,更待何时2 天前
06-04-A-RocketMQ存储深水区与源码解析详解
rocketmq
此时不提桶,更待何时2 天前
06-02-A-RocketMQ消息特性与消费机制详解
rocketmq
青山木11 天前
RocketMQ 入门到原理(六):可靠性全景
java·后端·中间件·架构·rocketmq
青山木11 天前
RocketMQ 入门到原理(五):特殊消息类型
java·后端·中间件·架构·rocketmq
青山木12 天前
RocketMQ 入门到原理(三):消息存储原理
java·后端·中间件·架构·rocketmq
科学熊12 天前
RocketMQ 一主两从集群搭建与 SpringBoot 集成完整方案
rocketmq