RocketMQ简介
RocketMQ是一种分布式消息中间件,它由阿里巴巴集团开发,并且后来捐献给了Apache软件基金会。RocketMQ最初是为了解决阿里巴巴内部因业务增长带来的高吞吐量需求而设计的。随着其不断发展和完善,RocketMQ已经成为了一个能够处理从传统发布/订阅模式到大规模实时无差错交易系统的强大消息引擎。
RocketMQ的主要特点
- 架构简洁:相比其他消息队列系统,RocketMQ具有更简单的架构设计。
- 丰富的业务功能:支持多种消息类型和应用场景,比如实时消息处理、顺序消息处理以及事务消息处理。
- 极高的可扩展性:可以轻松地进行水平扩展以满足不同规模的应用需求。
- 金融级可靠性:经过长时间在实际生产环境中的验证,被广泛认可为适用于对数据准确性和一致性要求极高的金融场景下的消息- 传递解决方案。
与其它消息队列系统的比较
- Kafka 更适合于大量数据处理(如离线流处理);
- RabbitMQ 则擅长处理复杂的消息路由及支持多种协议;
- ActiveMQ 提供了广泛的协议支持但性能相对较低。
官方网站:http://rocketmq.apache.org
项目地址:https://github.com/apache/rocketmq
中文社区:https://rocketmq.io/
集群模式介绍
RocketMQ 技术架构中包含的角色有NameServer、Broker、Proxy、Controller、dashboard、Producer、Consumer等。
NameServer
是 RocketMQ 的路由服务集群,它不保存任何消息数据,而是维护着所有 Broker 的路由信息(包括 Broker 存活情况、各 topic 的路由信息等)Broker
是 RocketMQ 的核心服务节点,负责接收来自 Producer(生产者)的消息、存储消息以及将消息转发给 Consumer(消费者)。在 RocketMQ 架构中,Broker 分为 Master Broker 和 Slave Broker(或称为 Replica)两种角色Proxy
是 RocketMQ 为了提高性能和简化客户端接入而引入的一个可选组件。它作为一个轻量级的代理服务器,位于客户端与 Broker 之间Controller
是 RocketMQ 5.0 新增的组件,它充当控制平面的角色,负责管理和协调系统的整体状态。它主要出现在可切换架构的部署过程中,如 Broker 宕机时,它将进行调度,对 Broker 集群进行选举管理。Controller 本身也支持集群部署,基于 Raft 实现容灾。Dashboard
是 RocketMQ 提供的一款可视化管理界面,它允许用户通过网页浏览器直观地监控和管理 RocketMQ 集群的状态,包括但不限于查看消息队列、消费进度、Broker 健康状况、主题配置、消费组详情等信息。Producer
与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer获取Topic路由信息,并向提供Topic 服务的Master建立长连接,且定时向Master发送心跳。Producer完全无状态,可集群部署。Consumer
与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer获取Topic路由信息,并向提供Topic服务的Master、Slave建立长连接,且定时向Master、Slave发送心跳。
RocketMQ集群迭代历程:
- 在RocketMQ 4.5版本之前,使用简单的Master-slave主从模式,如果Master宕机,不支持自动将Slave切换为Master,需要人工介入
- 在RocketMQ 4.5版本之后,引入了DLedger来解决Master/Slave的自动主从切换问题,该机制基于Raft协议实现,但存在局限性
- 在RocketMQ 5.0版本之后,引入controller组件,基于Dledger Controller实现主从切换
Proxy 组件部署有两种方式:
- Local 模式:将 Proxy 与 Broker 一起部署在同一个进程中,这能够节约一些机器资源。
- Cluster 模式:将 Proxy 作为一个独立集群进行部署。这能够提供较强的横向扩展能力。
Controller 组件部署有两种方式:
- 嵌入于 NameServer 进行部署,可以通过配置 enableControllerInNamesrv 打开。
- 另一种是独立部署,需要单独部署 Controller 组件。
数据存储分为同步刷盘和异步刷盘:
- 同步刷盘:当消息到达 Broker 后,只有把消息写入到 CommitLog 日志文件中,才给生产者返回发送成功的响应。
- 异步刷盘:当消息到达 Broker 后,就给生产者返回数据发送成功了,并启动一个异步线程去把消息写入到 CommitLog 中。
主从同步分为同步复制和异步复制:
-
每个Master配置一个Slave,有多组 Master-Slave,HA采用异步复制方式,主备有短暂消息延迟(毫秒级),优点是性能同多Master模式几乎一样,缺点是Master宕机磁盘损坏情况下会丢失少量消息。
-
每个Master配置一个Slave,有多组 Master-Slave,HA采用同步双写方式,即只有主备都写成功,才向应用返回成功。优点是数据与服务都无单点故障,缺点是性能比异步复制模式略低
集群部署规划
本示例基于RocketMQ 5.0 controller模式,采用异步刷盘、同步复制方式,所有组件分离部署:
- proxy为无状态组件,可以部署1至多个节点,本示例为2节点冗余部署
- nameserver为无状态组件,可以部署1至多个节点,本示例为2节点冗余部署
- controller基于raft协议,需要部署至少3个节点,本示例为3节点冗余部署
- broker部署2个副本组,每个副本组包含1个主节点和1个从节点,主从选举及故障切换由controller组件自动管理
- dashboard为无状态组件,可以部署1至多个节点,本示例为2节点冗余部署
- LB节点通过haproxy和keepalived实现,作为proxy和dashboard的统一负载均衡入口,本示例为2节点冗余部署
节点规划清单如下:
主机名 | IP地址 | 角色 | 操作系统 | CPU/内存/磁盘 |
---|---|---|---|---|
LB01 | 192.168.72.18 | 负载均衡器 | Ubuntu 22.04 LTS | 2C /4GB/100GB DATA DISK |
LB02 | 192.168.72.19 | 负载均衡器 | Ubuntu 22.04 LTS | 2C /4GB/100GB DATA DISK |
proxy01 | 192.168.72.31 | Proxy节点 | Ubuntu 22.04 LTS | 2C /4GB/100GB DATA DISK |
proxy02 | 192.168.72.32 | Proxy节点 | Ubuntu 22.04 LTS | 2C /4GB/100GB DATA DISK |
nameserver01 | 192.168.72.33 | NameServer节点 | Ubuntu 22.04 LTS | 2C /4GB/100GB DATA DISK |
nameserver02 | 192.168.72.34 | NameServer节点 | Ubuntu 22.04 LTS | 2C /4GB/100GB DATA DISK |
broker-1-1 | 192.168.72.51 | Broker副本组1-1 | Ubuntu 22.04 LTS | 2C /8GB/100GB DATA DISK |
broker-1-2 | 192.168.72.52 | Broker副本组1-2 | Ubuntu 22.04 LTS | 2C /8GB/100GB DATA DISK |
broker-2-1 | 192.168.72.53 | Broker副本组2-1 | Ubuntu 22.04 LTS | 2C /8GB/100GB DATA DISK |
broker-2-2 | 192.168.72.54 | Broker副本组2-2 | Ubuntu 22.04 LTS | 2C /8GB/100GB DATA DISK |
controller01 | 192.168.72.40 | Controller节点 | Ubuntu 22.04 LTS | 2C /4GB/100GB DATA DISK |
controller02 | 192.168.72.41 | Controller节点 | Ubuntu 22.04 LTS | 2C /4GB/100GB DATA DISK |
controller03 | 192.168.72.42 | Controller节点 | Ubuntu 22.04 LTS | 2C /4GB/100GB DATA DISK |
dashboard01 | 192.168.72.55 | Dashboard管理节点 | Ubuntu 22.04 LTS | 2C /4GB/100GB DATA DISK |
dashboard02 | 192.168.72.56 | Dashboard管理节点 | Ubuntu 22.04 LTS | 2C /4GB/100GB DATA DISK |
proxy VIP | 192.168.72.250 | proxy VIP | N/A | N/A |
dashboard VIP | 192.168.72.251 | dashboard VIP | N/A | N/A |
节点配置说明:
- 可视情况合并部分组件复用一个节点部署,nameserver、broker为必选组件
- broker 至少8G内存,生产环境建议提高配置,例如8C 16G 500G SSD,数据盘可单独挂载至
/data
目录 - 提供两个分离的VIP地址,一个作为rocketmq proxy统一入口,一个作为rocketmq dashboard统一入口
集群架构如下图所示:
部署目录规划
- 安装目录:统一安装包及配置文件存放路径,如
/opt/rocketmq/
- 数据目录:运行过程中生成的日志和数据文件与安装包分开,存放在
/data/
目录下。 - 服务管理:通过
systemd
管理服务,保证开机自启和管理规范化。
基础环境配置
配置主机名,在所有节点执行,每个节点单独配置。
hostnamectl set-hostname nameserver01
hostnamectl set-hostname nameserver02
hostnamectl set-hostname controller01
hostnamectl set-hostname controller02
hostnamectl set-hostname controller03
hostnamectl set-hostname broker-1-1
hostnamectl set-hostname broker-1-2
hostnamectl set-hostname broker-2-1
hostnamectl set-hostname broker-2-2
hostnamectl set-hostname dashboard01
hostnamectl set-hostname dashboard02
hostnamectl set-hostname proxy01
hostnamectl set-hostname proxy02
hostnamectl set-hostname lb01
hostnamectl set-hostname lb02
配置所有节点时间同步,默认与互联网NTP同步时间
apt install -y chrony
systemctl enable --now chrony
基础软件安装,在所有非LB节点执行。
apt update -y
apt install -y unzip
apt install -y openjdk-11-jdk
依赖说明:
- RocketMQ依赖JAVA环境,因此需要安装openjdk,注意版本兼容性
- 官方二进制包解压需要使用unzip工具
操作系统初始化,在所有非LB节点执行,配置RocketMQ相关系统参数。
wget https://raw.githubusercontent.com/apache/rocketmq/refs/heads/develop/distribution/bin/os.sh
bash os.sh
部署 RocketMQ 软件包
以下操作在所有非LB节点执行。
下载二进制文件,以使用RocketMQ 5.3.1版本二进制包安装为例。
wget https://dist.apache.org/repos/dist/release/rocketmq/5.3.1/rocketmq-all-5.3.1-bin-release.zip
将 rocketmq-all-5.3.1-bin-release.zip
上传到目标服务器。执行以下命令解压到/opt目录下:
# 解压安装包到指定目录
sudo unzip rocketmq-all-5.3.1-bin-release.zip -d /opt
# 创建软链接,便于后续升级管理
sudo ln -s /opt/rocketmq-all-5.3.1-bin-release /opt/rocketmq
配置环境变量,方便调用相关bin二进制命令
cat >/etc/profile.d/rocketmq.sh<<'EOF'
export ROCKETMQ_HOME=/opt/rocketmq
export PATH=$ROCKETMQ_HOME/bin:$PATH
EOF
source /etc/profile
部署 NameServer 组件
在所有nameserver
节点操作。
创建 systemd 服务文件
在 /etc/systemd/system/
目录下创建一个 rocketmq-namesrv.service
文件。写入以下内容:
cat >/etc/systemd/system/rocketmq-namesrv.service<<'EOF'
[Unit]
Description=RocketMQ NameServer
After=network.target
[Service]
Type=simple
User=root
ExecStart=/opt/rocketmq/bin/mqnamesrv
ExecStop=/bin/kill -SIGTERM $MAINPID
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
Environment="ROCKETMQ_HOME=/opt/rocketmq"
Environment="JAVA_OPT=-Duser.home=/data/rocketmq-namesrv"
[Install]
WantedBy=multi-user.target
EOF
启用并启动 NameServer 服务
执行以下命令:
# 启动 NameServer 服务
sudo systemctl start rocketmq-namesrv
# 设置开机自启
sudo systemctl enable rocketmq-namesrv
# 检查服务状态
sudo systemctl status rocketmq-namesrv
# 重启服务(可选)
systemctl daemon-reload
systemctl restart rocketmq-namesrv
示例输出结果
root@nameserver01:~# systemctl status rocketmq-namesrv
● rocketmq-namesrv.service - RocketMQ NameServer
Loaded: loaded (/etc/systemd/system/rocketmq-namesrv.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2024-12-22 15:27:03 CST; 1min 36s ago
Main PID: 112830 (mqnamesrv)
Tasks: 74 (limit: 4557)
Memory: 240.4M
CPU: 5.388s
CGroup: /system.slice/rocketmq-namesrv.service
├─112830 /bin/sh /opt/rocketmq/bin/mqnamesrv
├─112831 sh /opt/rocketmq/bin/runserver.sh -Drmq.logback.configurationFile=/opt/rocketmq/conf/rmq.namesrv.logback.xml org.apache.rocketmq.namesrv.NamesrvStartup
└─112858 /usr/lib/jvm/java-11-openjdk-amd64/bin/java -Duser.home=/data/rocketmq-namesrv -server -Xms4g -Xmx4g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m -XX:+UseG1GC -XX:G1Heap>
Dec 22 15:27:03 nameserver01 systemd[1]: Started RocketMQ NameServer.
Dec 22 15:27:05 nameserver01 mqnamesrv[112858]: The Name Server boot success. serializeType=JSON, address 0.0.0.0:9876
日志检查与验证
NameServer 默认的日志目录位于home目录下,可通过以下命令检查:
tail -f /data/rocketmq-namesrv/logs/rocketmqlogs/namesrv.log
确保 NameServer 服务正常监听在 9876 端口:
root@nameserver01:~# ss -tlnp | grep 9876
LISTEN 0 1024 *:9876 *:* users:(("java",pid=7363,fd=152))
部署 Controller 组件
以下操作在controller节点执行。
修改controller配置文件
创建controller01
节点配置文件,在Controller01
节点操作。
cat >/opt/rocketmq/conf/controller/controller.conf<<EOF
controllerDLegerGroup = group1
controllerDLegerPeers = n0-192.168.72.40:9878;n1-192.168.72.41:9878;n2-192.168.72.42:9878
controllerDLegerSelfId = n0
controllerStorePath = /data/admin/DledgerController
EOF
创建controller02
节点配置文件,在Controller02
节点操作。
cat >/opt/rocketmq/conf/controller/controller.conf<<EOF
controllerDLegerGroup = group1
controllerDLegerPeers = n0-192.168.72.40:9878;n1-192.168.72.41:9878;n2-192.168.72.42:9878
controllerDLegerSelfId = n1
controllerStorePath = /data/admin/DledgerController
EOF
创建controller03
节点配置文件,在Controller03
节点操作。
cat >/opt/rocketmq/conf/controller/controller.conf<<EOF
controllerDLegerGroup = group1
controllerDLegerPeers = n0-192.168.72.40:9878;n1-192.168.72.41:9878;n2-192.168.72.42:9878
controllerDLegerSelfId = n2
controllerStorePath = /data/admin/DledgerController
EOF
创建 systemd 服务文件
在所有Controller
节点操作。
在 /etc/systemd/system/
目录下创建一个 rocketmq-controller.service
文件。写入以下内容:
cat >/etc/systemd/system/rocketmq-controller.service<<'EOF'
[Unit]
Description=RocketMQ Controller
After=network.target
[Service]
Type=simple
User=root
ExecStart=/opt/rocketmq/bin/mqcontroller -c /opt/rocketmq/conf/controller/controller.conf
ExecStop=/bin/kill -SIGTERM $MAINPID
Restart=on-failure
RestartSec=5
Environment="ROCKETMQ_HOME=/opt/rocketmq"
Environment="JAVA_OPT=-Duser.home=/data/admin"
[Install]
WantedBy=multi-user.target
EOF
启用并启动 controller 服务
在所有Controller
节点操作,执行以下命令:
# 启动 Controller 服务
sudo systemctl start rocketmq-controller
# 设置开机自启
sudo systemctl enable rocketmq-controller
# 检查服务状态
sudo systemctl status rocketmq-controller
# 重启服务(可选)
systemctl daemon-reload
systemctl restart rocketmq-controller
示例输出如下
root@controller01:~# systemctl status rocketmq-controller.service
● rocketmq-controller.service - RocketMQ Controller
Loaded: loaded (/etc/systemd/system/rocketmq-controller.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2024-12-22 15:31:23 CST; 2min 19s ago
Main PID: 124707 (mqcontroller)
Tasks: 89 (limit: 4556)
Memory: 314.1M
CPU: 26.095s
CGroup: /system.slice/rocketmq-controller.service
├─124707 /bin/sh /opt/rocketmq/bin/mqcontroller -c /opt/rocketmq/conf/controller/controller.conf
├─124708 sh /opt/rocketmq/bin/runserver.sh -Drmq.logback.configurationFile=/opt/rocketmq/conf/rmq.controller.logback.xml org.apache.rocketmq.controller.ControllerStartup -c /opt/rock>
└─124735 /usr/lib/jvm/java-11-openjdk-amd64/bin/java -Duser.home=/data/admin -server -Xms4g -Xmx4g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m -XX:+UseG1GC -XX:G1HeapRegionSize=>
Dec 22 15:31:23 controller01 systemd[1]: Started RocketMQ Controller.
Dec 22 15:31:25 controller01 mqcontroller[124735]: load config properties file OK, /opt/rocketmq/conf/controller/controller.conf
Dec 22 15:31:26 controller01 mqcontroller[124735]: WARNING: An illegal reflective access operation has occurred
Dec 22 15:31:26 controller01 mqcontroller[124735]: WARNING: Illegal reflective access by com.caucho.hessian.io.JavaDeserializer (file:/opt/rocketmq-all-5.3.1-bin-release/lib/hessian-3.3.6.jar) to>
Dec 22 15:31:26 controller01 mqcontroller[124735]: WARNING: Please consider reporting this to the maintainers of com.caucho.hessian.io.JavaDeserializer
Dec 22 15:31:26 controller01 mqcontroller[124735]: WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
Dec 22 15:31:26 controller01 mqcontroller[124735]: WARNING: All illegal access operations will be denied in a future release
Dec 22 15:31:27 controller01 mqcontroller[124735]: The Controller Server boot success. serializeType=JSON
日志检查与验证
Controller 默认的日志目录位于home目录下,可通过以下命令检查:
tail -f /data/admin/logs/rocketmqlogs/controller.log
确保 Controller 服务正常监听在 9878 端口:
root@controller01:~# ss -tlnp | grep 9878
LISTEN 0 1024 *:9878 *:* users:(("java",pid=121984,fd=157))