网上大部分 RocketMQ Docker 部署教程都是单机版,拿来学习可以,上生产就是给自己埋雷。
本文基于 RocketMQ 5.3.2 ,用 3 台机器搭建 2 主 2 从 + 3 NameServer + Dashboard + Proxy 的完整集群,采用 Docker Host 网络模式,所有命令可直接复制执行。
一、为什么选 Docker Host 模式?
部署 RocketMQ 集群有三种方式:
| 方式 | 优点 | 缺点 |
|---|---|---|
| 裸机部署 | 性能最优,无网络损耗 | 依赖管理麻烦,环境不一致 |
| Docker Bridge | 隔离性好 | Broker 注册 IP 是容器内网 IP,客户端连不上(需额外配置) |
| Docker Host | 兼顾容器化和网络直通,Broker 注册宿主机 IP | 端口直接占用宿主机 |
Broker 需要向 NameServer 注册自己的 IP,客户端通过这个 IP 直连 Broker。Bridge 模式下注册的是容器内网 IP,外部客户端无法访问------这是 RocketMQ Docker 部署最常见的坑。Host 模式直接绕过这个问题。
二、集群架构
2.1 集群规划
| 机器 | 组件 |
|---|---|
| 10.0.1.1 | NameServer + Broker-a(Master)+ Broker-b(Slave) |
| 10.0.1.2 | NameServer + Dashboard |
| 10.0.1.3 | NameServer + Broker-b(Master)+ Broker-a(Slave) |
为什么主从交叉部署?
机器 10.0.1.1:broker-a(主) + broker-b(从)
机器 10.0.1.3:broker-b(主) + broker-a(从)
任意一台挂了,每个 Broker 都还有副本在另一台,消息不丢、服务不断。如果把 broker-a 的主从都放在同一台,那台机器一挂,broker-a 就完全不可用了。
2.2 端口规划
| 端口 | 用途 | 说明 |
|---|---|---|
| 9876 | NameServer | 3 台都有 |
| 10911 | Broker Master 客户端通信 | 生产者/消费者连这个端口 |
| 10912 | Broker Master HA 复制 | 主从数据同步 |
| 10921 | Broker Slave 客户端通信 | 同机器第二个 Broker,避免端口冲突 |
| 10922 | Broker Slave HA 复制 | 同上 |
| 8081 | Proxy gRPC 入口 | 5.x 新特性,仅 Master 启用 |
| 8080 | Proxy HTTP 入口 | 与 gRPC 端口配套,可通过 rmq-proxy.json 自定义 |
| 10080 | Dashboard(宿主机映射) | 容器内部端口 8082,通过 -p 10080:8082 映射 |
同一台机器上跑两个 Broker(一主一从),所以 Slave 用 10921/10922 错开端口。
2.3 架构图
┌─────────────┐
│ 客户端应用 │
└──────┬──────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ NameServer-1 │ │ NameServer-2 │ │ NameServer-3 │
│ 10.0.1.1 │ │ 10.0.1.2 │ │ 10.0.1.3 │
└──────────────┘ └──────┬───────┘ └──────────────┘
│
Dashboard
(10.0.1.2:10080)
┌────────────────────┐ ┌────────────────────┐
│ 10.0.1.1 │ │ 10.0.1.3 │
│ ┌────────────────┐ │ │ ┌────────────────┐ │
│ │ broker-a Master│ │◄────►│ │ broker-a Slave │ │
│ │ :10911 +Proxy │ │ HA │ │ :10921 │ │
│ └────────────────┘ │ │ └────────────────┘ │
│ ┌────────────────┐ │ │ ┌────────────────┐ │
│ │ broker-b Slave │ │◄────►│ │ broker-b Master│ │
│ │ :10921 │ │ HA │ │ :10911 +Proxy │ │
│ └────────────────┘ │ │ └────────────────┘ │
└────────────────────┘ └────────────────────┘
三、开始部署
3.1 前置准备(3 台机器都执行)
shell
# 拉取镜像
docker pull apache/rocketmq:5.3.2
# 创建目录
mkdir -p /data/rocketmq/namesrv/logs
mkdir -p /data/rocketmq/conf
# 查看容器内 rocketmq 用户的 uid(结果是 3000)
# docker run --rm apache/rocketmq:5.3.2 id
# 设置目录权限,确保容器内进程有读写权限
chown -R 3000:3000 /data/rocketmq
3.2 Proxy 配置(可选,仅部署 Master 的机器)
如果默认 gRPC 端口 8081 / http 端口 8080 被其他服务占用,需要自定义 Proxy 端口:
shell
cat > /data/rocketmq/conf/rmq-proxy.json << 'EOF'
{
"grpcServerPort": 8091,
"remotingListenPort": 8090
}
EOF
如果 8081 / 8080 没有冲突,可以跳过此步,不影响后续部署。
踩坑提醒 :Proxy 的 HTTP 端口配置项叫 remotingListenPort,不是你以为的 httpServerPort。网上搜不到,AI 也答错了,最后翻源码才找到。别问我怎么知道的,半天就这么没了。


3.3 创建 Broker 配置文件
4 个 Broker 实例的配置文件大同小异,核心差异如下:
| 配置文件 | brokerName | brokerId | brokerIP1 | listenPort | haListenPort | brokerRole | 部署机器 |
|---|---|---|---|---|---|---|---|
| broker-a.properties | broker-a | 0 | 10.0.1.1 | 10911 | 10912 | ASYNC_MASTER | 10.0.1.1 |
| broker-b-s.properties | broker-b | 1 | 10.0.1.1 | 10921 | 10922 | SLAVE | 10.0.1.1 |
| broker-b.properties | broker-b | 0 | 10.0.1.3 | 10911 | 10912 | ASYNC_MASTER | 10.0.1.3 |
| broker-a-s.properties | broker-a | 1 | 10.0.1.3 | 10921 | 10922 | SLAVE | 10.0.1.3 |
关键参数说明:
brokerId=0表示 Master,brokerId=1表示 Slave- 同名 Broker(如 broker-a)的主从通过相同的
brokerName自动配对brokerIP1必须填宿主机 IP,这是注册到 NameServer 的地址
在 10.0.1.1 上执行
shell
mkdir -p /data/rocketmq/broker-a/store /data/rocketmq/broker-a/logs
mkdir -p /data/rocketmq/broker-b-s/store /data/rocketmq/broker-b-s/logs
# broker-a Master
cat > /data/rocketmq/conf/broker-a.properties << 'EOF'
brokerClusterName=DefaultCluster
brokerName=broker-a
brokerId=0
namesrvAddr=10.0.1.1:9876;10.0.1.2:9876;10.0.1.3:9876
brokerIP1=10.0.1.1
listenPort=10911
haListenPort=10912
storePathRootDir=/home/rocketmq/store
storePathCommitLog=/home/rocketmq/store/commitlog
deleteWhen=04
fileReservedTime=48
brokerRole=ASYNC_MASTER
flushDiskType=ASYNC_FLUSH
autoCreateTopicEnable=false
autoCreateSubscriptionGroup=false
slaveReadEnable=true
EOF
# broker-b Slave
cat > /data/rocketmq/conf/broker-b-s.properties << 'EOF'
brokerClusterName=DefaultCluster
brokerName=broker-b
brokerId=1
namesrvAddr=10.0.1.1:9876;10.0.1.2:9876;10.0.1.3:9876
brokerIP1=10.0.1.1
listenPort=10921
haListenPort=10922
storePathRootDir=/home/rocketmq/store
storePathCommitLog=/home/rocketmq/store/commitlog
deleteWhen=04
fileReservedTime=48
brokerRole=SLAVE
flushDiskType=ASYNC_FLUSH
autoCreateTopicEnable=false
autoCreateSubscriptionGroup=false
slaveReadEnable=true
EOF
在 10.0.1.3 上执行
shell
mkdir -p /data/rocketmq/broker-b/store /data/rocketmq/broker-b/logs
mkdir -p /data/rocketmq/broker-a-s/store /data/rocketmq/broker-a-s/logs
# broker-b Master
cat > /data/rocketmq/conf/broker-b.properties << 'EOF'
brokerClusterName=DefaultCluster
brokerName=broker-b
brokerId=0
namesrvAddr=10.0.1.1:9876;10.0.1.2:9876;10.0.1.3:9876
brokerIP1=10.0.1.3
listenPort=10911
haListenPort=10912
storePathRootDir=/home/rocketmq/store
storePathCommitLog=/home/rocketmq/store/commitlog
deleteWhen=04
fileReservedTime=48
brokerRole=ASYNC_MASTER
flushDiskType=ASYNC_FLUSH
autoCreateTopicEnable=false
autoCreateSubscriptionGroup=false
slaveReadEnable=true
EOF
# broker-a Slave
cat > /data/rocketmq/conf/broker-a-s.properties << 'EOF'
brokerClusterName=DefaultCluster
brokerName=broker-a
brokerId=1
namesrvAddr=10.0.1.1:9876;10.0.1.2:9876;10.0.1.3:9876
brokerIP1=10.0.1.3
listenPort=10921
haListenPort=10922
storePathRootDir=/home/rocketmq/store
storePathCommitLog=/home/rocketmq/store/commitlog
deleteWhen=04
fileReservedTime=48
brokerRole=SLAVE
flushDiskType=ASYNC_FLUSH
autoCreateTopicEnable=false
autoCreateSubscriptionGroup=false
slaveReadEnable=true
EOF
其他 Broker 配置参数说明:
| 参数 | 值 | 说明 |
|---|---|---|
deleteWhen |
04 | 凌晨 4 点清理过期消息 |
fileReservedTime |
48 | 消息文件保留 48 小时 |
brokerRole |
ASYNC_MASTER | 异步复制(性能优先),同步用 SYNC_MASTER |
flushDiskType |
ASYNC_FLUSH | 异步刷盘(性能优先),同步用 SYNC_FLUSH |
autoCreateTopicEnable |
false | 生产环境关闭自动创建 Topic,避免误操作 |
slaveReadEnable |
true | 允许从 Slave 读消息,分担 Master 压力 |
四、启动集群
4.1 启动 NameServer(3 台机器都执行)
shell
docker run -d \
--name=rocketmq-namesrv \
--network=host \
--restart=unless-stopped \
-e "JAVA_OPT_EXT=-Xms512m -Xmx512m -Xmn256m" \
-v /data/rocketmq/namesrv/logs:/home/rocketmq/logs \
apache/rocketmq:5.3.2 \
sh mqnamesrv
验证:
shell
# 看到 "The Name Server boot success" 即成功
docker logs -f rocketmq-namesrv --tail 20
4.2 启动 Broker(10.0.1.1)
shell
# Broker-a Master(带 Proxy)
docker run -d \
--name=rocketmq-broker-a \
--network=host \
--restart=unless-stopped \
-e "JAVA_OPT_EXT=-Xms2g -Xmx2g -Xmn1g" \
-e "NAMESRV_ADDR=10.0.1.1:9876;10.0.1.2:9876;10.0.1.3:9876" \
-v /data/rocketmq/broker-a/store:/home/rocketmq/store \
-v /data/rocketmq/broker-a/logs:/home/rocketmq/logs \
-v /data/rocketmq/conf/broker-a.properties:/home/rocketmq/rocketmq-5.3.2/conf/broker.conf \
-v /data/rocketmq/conf/rmq-proxy.json:/home/rocketmq/rocketmq-5.3.2/conf/rmq-proxy.json \
apache/rocketmq:5.3.2 \
sh mqbroker -c /home/rocketmq/rocketmq-5.3.2/conf/broker.conf --enable-proxy
# Broker-b Slave
docker run -d \
--name=rocketmq-broker-b-s \
--network=host \
--restart=unless-stopped \
-e "JAVA_OPT_EXT=-Xms1g -Xmx1g -Xmn512m" \
-v /data/rocketmq/broker-b-s/store:/home/rocketmq/store \
-v /data/rocketmq/broker-b-s/logs:/home/rocketmq/logs \
-v /data/rocketmq/conf/broker-b-s.properties:/home/rocketmq/rocketmq-5.3.2/conf/broker.conf \
apache/rocketmq:5.3.2 \
sh mqbroker -c /home/rocketmq/rocketmq-5.3.2/conf/broker.conf
--enable-proxy只在 Master 上加,Slave 不需要。Proxy 是 RocketMQ 5.x 的入口,Local 模式下与 Broker 同进程,会额外占用 gRPC 端口(默认 8081)和 HTTP 端口(默认 8080)。如果自定义了 Proxy 端口(3.2 节),Master 的 docker run 需要挂载
rmq-proxy.json(上面的命令已包含)。如果没有自定义,去掉该挂载行即可。
4.3 启动 Broker(10.0.1.3)
shell
# Broker-b Master(带 Proxy)
docker run -d \
--name=rocketmq-broker-b \
--network=host \
--restart=unless-stopped \
-e "JAVA_OPT_EXT=-Xms2g -Xmx2g -Xmn1g" \
-e "NAMESRV_ADDR=10.0.1.1:9876;10.0.1.2:9876;10.0.1.3:9876" \
-v /data/rocketmq/broker-b/store:/home/rocketmq/store \
-v /data/rocketmq/broker-b/logs:/home/rocketmq/logs \
-v /data/rocketmq/conf/broker-b.properties:/home/rocketmq/rocketmq-5.3.2/conf/broker.conf \
-v /data/rocketmq/conf/rmq-proxy.json:/home/rocketmq/rocketmq-5.3.2/conf/rmq-proxy.json \
apache/rocketmq:5.3.2 \
sh mqbroker -c /home/rocketmq/rocketmq-5.3.2/conf/broker.conf --enable-proxy
# Broker-a Slave
docker run -d \
--name=rocketmq-broker-a-s \
--network=host \
--restart=unless-stopped \
-e "JAVA_OPT_EXT=-Xms1g -Xmx1g -Xmn512m" \
-v /data/rocketmq/broker-a-s/store:/home/rocketmq/store \
-v /data/rocketmq/broker-a-s/logs:/home/rocketmq/logs \
-v /data/rocketmq/conf/broker-a-s.properties:/home/rocketmq/rocketmq-5.3.2/conf/broker.conf \
apache/rocketmq:5.3.2 \
sh mqbroker -c /home/rocketmq/rocketmq-5.3.2/conf/broker.conf
4.4 启动 Dashboard(10.0.1.2)
shell
docker run -d \
--name=rocketmq-dashboard \
-p 10080:8082 \
--restart=unless-stopped \
-e "JAVA_OPTS=-Xms256m -Xmx256m -Drocketmq.namesrv.addr=10.0.1.1:9876;10.0.1.2:9876;10.0.1.3:9876" \
apacherocketmq/rocketmq-dashboard:latest
访问 http://10.0.1.2:10080
为什么 Dashboard 没用 Host 模式? Dashboard 是纯 Web 管理界面,不涉及 Broker IP 注册问题,用 Bridge + 端口映射更灵活(想改端口改映射就行,不用改容器配置)。
Dashboard 最新版(v2.1.1)的内部端口已从 8080 改为 8082 ,映射时注意对应。如果访问不了,先看启动日志确认实际端口:
docker logs rocketmq-dashboard | grep "Tomcat started on port"
五、验证集群
shell
# 在任意一台有 Broker 的机器上执行
docker exec rocketmq-broker-a sh mqadmin clusterList -n 10.0.1.1:9876
期望输出(4 个节点,2 主 2 从):
Cluster Name Broker Name BID Addr Version
DefaultCluster broker-a 0 10.0.1.1:10911 V5_3_2
DefaultCluster broker-a 1 10.0.1.3:10921 V5_3_2
DefaultCluster broker-b 0 10.0.1.3:10911 V5_3_2
DefaultCluster broker-b 1 10.0.1.1:10921 V5_3_2
BID=0是 Master,BID=1是 Slave。两个 Broker 的主从分布在不同机器上,交叉部署正确。
六、ACL 权限控制(生产必配)
裸奔的 RocketMQ 谁都能连、谁都能发消息,生产环境必须开 ACL。RocketMQ 5.3.x 使用 ACL 2.0 ,基于元数据提供者机制,不再使用老版本的 plain_acl.yml。
6.1 Broker 开启 ACL
在所有 4 个 Broker 配置文件末尾追加:
properties
# ===== ACL 2.0 =====
authenticationEnabled=true
authenticationMetadataProvider=org.apache.rocketmq.auth.authentication.provider.LocalAuthenticationMetadataProvider
authorizationEnabled=true
authorizationMetadataProvider=org.apache.rocketmq.auth.authorization.provider.LocalAuthorizationMetadataProvider
# 初始化管理员账号(仅首次启动生效)
initAuthenticationUser={"username":"rocketmq","password":"YourStr0ngP@ssw0rd"}
# 组件间通信凭证(所有 Broker 必须一致)
innerClientAuthenticationCredentials={"accessKey":"rocketmq","secretKey":"YourStr0ngP@ssw0rd"}
追加后重启所有 Broker 容器生效(先 Slave 后 Master,减少对生产的影响):
shell
# --- 10.0.1.1 ---
docker restart rocketmq-broker-b-s # Slave 先重启
docker restart rocketmq-broker-a # Master 后重启
# --- 10.0.1.3 ---
docker restart rocketmq-broker-a-s # Slave 先重启
docker restart rocketmq-broker-b # Master 后重启
验证 Broker 重启成功:
shell
docker logs --tail 20 rocketmq-broker-a | grep "boot success"
initAuthenticationUser仅在 Broker 首次启动且无 ACL 元数据时生效。如果之前已初始化过用户,修改该配置不会覆盖,需通过 mqadmin 管理。
6.2 Dashboard 开启 ACL
shell
# 先删掉旧容器
docker rm -f rocketmq-dashboard
# 带 ACL 凭证重新启动
docker run -d \
--name=rocketmq-dashboard \
-p 10080:8082 \
--restart=unless-stopped \
-e "JAVA_OPTS=-Xms256m -Xmx256m \
-Drocketmq.namesrv.addr=10.0.1.1:9876;10.0.1.2:9876;10.0.1.3:9876 \
-Drocketmq.config.accessKey=rocketmq \
-Drocketmq.config.secretKey=YourStr0ngP@ssw0rd" \
apacherocketmq/rocketmq-dashboard:latest
6.3 mqadmin 工具配置
shell
# 创建凭证文件
cat > /data/rocketmq/conf/tools.yml << 'EOF'
accessKey: rocketmq
secretKey: YourStr0ngP@ssw0rd
EOF
# 拷贝到所有 Broker 容器内
# --- 10.0.1.1 ---
docker cp /data/rocketmq/conf/tools.yml rocketmq-broker-a:/home/rocketmq/rocketmq-5.3.2/conf/tools.yml
docker cp /data/rocketmq/conf/tools.yml rocketmq-broker-b-s:/home/rocketmq/rocketmq-5.3.2/conf/tools.yml
# --- 10.0.1.3 ---
docker cp /data/rocketmq/conf/tools.yml rocketmq-broker-b:/home/rocketmq/rocketmq-5.3.2/conf/tools.yml
docker cp /data/rocketmq/conf/tools.yml rocketmq-broker-a-s:/home/rocketmq/rocketmq-5.3.2/conf/tools.yml
容器重建后需要重新拷贝。如果想持久化,在 docker run 时加挂载:
-v /data/rocketmq/conf/tools.yml:/home/rocketmq/rocketmq-5.3.2/conf/tools.yml
6.4 用户管理
shell
# 创建业务用户
docker exec rocketmq-broker-a sh mqadmin createUser -n 10.0.1.1:9876 \
-c DefaultCluster -u app_user -p app_password
# 授权:允许发送和消费指定 Topic
docker exec rocketmq-broker-a sh mqadmin createAcl -n 10.0.1.1:9876 \
-c DefaultCluster -s app_user \
-r Topic=order_topic -a Pub,Sub
# 查看用户列表
docker exec rocketmq-broker-a sh mqadmin listUser -n 10.0.1.1:9876 -c DefaultCluster
6.5 客户端接入
Spring Boot(rocketmq-spring-boot-starter):
yaml
rocketmq:
name-server: 10.0.1.1:9876;10.0.1.2:9876;10.0.1.3:9876
producer:
access-key: app_user
secret-key: app_password
consumer:
access-key: app_user
secret-key: app_password
RocketMQ 5.x gRPC 客户端:
java
StaticSessionCredentialsProvider credentialsProvider =
new StaticSessionCredentialsProvider("app_user", "app_password");
ClientConfiguration config = ClientConfiguration.newBuilder()
.setEndpoints("10.0.1.1:8081") // Proxy gRPC 端口
.setCredentialProvider(credentialsProvider)
.build();
七、JVM 参数调优
按机器内存调整 JAVA_OPT_EXT:
| 组件 | 8G 机器 | 16G 机器 |
|---|---|---|
| NameServer | -Xms512m -Xmx512m |
-Xms1g -Xmx1g |
| Broker Master | -Xms2g -Xmx2g -Xmn1g |
-Xms4g -Xmx4g -Xmn2g |
| Broker Slave | -Xms1g -Xmx1g -Xmn512m |
-Xms2g -Xmx2g -Xmn1g |
| Dashboard | -Xms256m -Xmx256m |
-Xms256m -Xmx256m |
注意 :如果机器上还跑了其他服务(ES、Redis、应用等),需要更保守。比如共享 8G 机器,Master 给 1g、Slave 给 512m、NameServer 给 256m,RocketMQ 总占用控制在 ~1.8G 以内。
八、启停顺序
启动:NameServer(3 台) → Broker Master → Broker Slave → Dashboard
停止:Dashboard → Broker Slave → Broker Master → NameServer(反着来)
为什么这个顺序?
- NameServer 是注册中心,必须先启动,Broker 启动时要向它注册
- Master 先于 Slave,Slave 需要从 Master 同步数据
- 停止反着来,先停消费端 Dashboard,最后停注册中心
九、常见问题
1. Broker 启动报 connect to namesrv failed
NameServer 还没启动完就启动了 Broker。等 NameServer 日志出现 The Name Server boot success 再启动 Broker。
2. 客户端报 No route info of this topic
- Topic 没创建:
autoCreateTopicEnable=false时需要手动创建 Topic - NameServer 地址配错:确认客户端连的是正确的 NameServer 地址
shell
# 手动创建 Topic(详见第十节)
docker exec rocketmq-broker-a sh mqadmin updateTopic -n 10.0.1.1:9876 \
-c DefaultCluster -t order_topic \
--readQueueNums 4 --writeQueueNums 4 --perm 6 \
--attributes +message.type=NORMAL
3. Dashboard 打不开
- 确认映射端口没被占用:
ss -tlnp | grep 10080 - Dashboard 需要能连通 NameServer,检查网络
- 内部端口可能不是 8080(见问题 7),检查端口映射是否正确
4. Slave 一直不同步
检查 HA 端口(10912/10922)是否通:
shell
# 在 Slave 机器上测试连通性
telnet 10.0.1.1 10912
5. mqadmin 报 User:xxx is not found
MQBrokerException: CODE: 16 DESC: User:rocketmq2 is not found
开启 ACL 后,mqadmin 也需要认证凭证。按照 6.3 节配置 tools.yml 并拷贝到容器内即可。
6. Master 启动报 The configuration item NamesrvAddr is not configured
java.lang.RuntimeException: The configuration item NamesrvAddr is not configured
--enable-proxy 启用的 Proxy 组件(Local 模式)有自己独立的配置加载逻辑,不复用 broker.conf 里的 namesrvAddr,需要通过环境变量单独指定。启动命令加上:
shell
-e "NAMESRV_ADDR=10.0.1.1:9876;10.0.1.2:9876;10.0.1.3:9876" \
本文 4.2、4.3 节的 Master 启动命令已经包含了这个环境变量,直接复制不会踩坑。
7. Dashboard 映射 8080 端口访问不了
Dashboard 最新版(v2.1.1,基于 Spring Boot 3.4.5)的内部端口已从 8080 变为 8082。如果你还在映射 8080,自然访问不了。
确认实际端口:
shell
docker logs rocketmq-dashboard | grep "Tomcat started on port"
# 输出:Tomcat started on port 8082 (http)
映射时用 -p 10080:8082(本文 4.4 节的命令已更新)。这个跟 Dashboard 版本有关,不同版本端口可能不一样,遇到问题先看启动日志。
十、创建 Topic
本文配置了 autoCreateTopicEnable=false,生产环境必须手动创建 Topic。
10.1 手动创建 Topic
shell
docker exec rocketmq-broker-a sh mqadmin updateTopic \
-n 10.0.1.1:9876 \
-c DefaultCluster \
-t order_topic \
--readQueueNums 4 --writeQueueNums 4 \
--perm 6 \
--attributes +message.type=NORMAL
参数说明:
| 参数 | 说明 |
|---|---|
-t |
Topic 名称 |
--readQueueNums / --writeQueueNums |
读写队列数,一般设为相同值,按消费者数量调整 |
--perm 6 |
权限:6 = 读写,4 = 只读,2 = 只写 |
--attributes +message.type= |
消息类型:NORMAL(普通)、TRANSACTION(事务)、FIFO(顺序)、DELAY(延迟) |
如果 Topic 较多,可以用脚本批量创建:
shell
NAMESRV='10.0.1.1:9876;10.0.1.2:9876;10.0.1.3:9876'
CLUSTER='DefaultCluster'
BROKER='rocketmq-broker-a'
# 普通消息 Topic
for topic in user-update notify-event; do
docker exec $BROKER sh mqadmin updateTopic \
--namesrvAddr "$NAMESRV" --clusterName $CLUSTER \
--topic $topic --perm 6 --readQueueNums 4 --writeQueueNums 4 \
--attributes +message.type=NORMAL
done
# 事务消息 Topic
for topic in order-create payment-refund; do
docker exec $BROKER sh mqadmin updateTopic \
--namesrvAddr "$NAMESRV" --clusterName $CLUSTER \
--topic $topic --perm 6 --readQueueNums 4 --writeQueueNums 4 \
--attributes +message.type=TRANSACTION
done
10.2 想偷懒?开启自动创建 Topic
如果是开发/测试环境 ,不想每次手动建 Topic,可以开启自动创建。修改所有 Broker 配置文件中的两个参数:
properties
autoCreateTopicEnable=true
autoCreateSubscriptionGroup=true
然后重启所有 Broker 即可。客户端发送消息时,如果 Topic 不存在会自动创建。
生产环境强烈不建议开启,原因:
- 自动创建的 Topic 只会落在第一个接收到消息的 Broker 上,不会均匀分布到集群所有节点,导致负载不均
- 拼错 Topic 名称不会报错,而是悄悄创建一个新 Topic,排查起来很痛苦
- 无法控制队列数和消息类型,默认参数可能不符合业务需求
十一、总结
整个集群的部署并不复杂,核心就是理解 "主从交叉" 和 "端口错开" 两个概念:
- 主从交叉:broker-a 的主在机器 1,从在机器 3;broker-b 反过来。任一台挂了不影响消息收发
- 端口错开:同一台机器跑两个 Broker,Master 用 10911/10912,Slave 用 10921/10922
最后附一张全局视角:
| 机器 | 进程 | 端口 | 角色 |
|---|---|---|---|
| 10.0.1.1 | NameServer | 9876 | 注册中心 |
| 10.0.1.1 | broker-a | 10911/10912/8081 | Master + Proxy |
| 10.0.1.1 | broker-b | 10921/10922 | Slave |
| 10.0.1.2 | NameServer | 9876 | 注册中心 |
| 10.0.1.2 | Dashboard | 10080→8082 | Web 管理 |
| 10.0.1.3 | NameServer | 9876 | 注册中心 |
| 10.0.1.3 | broker-b | 10911/10912/8081 | Master + Proxy |
| 10.0.1.3 | broker-a | 10921/10922 | Slave |
如果这篇文章帮你省了一天折腾环境的时间,点个赞再走呗。
毕竟,把 3 台机器配成集群这事,第二次做就不想再踩一遍坑了。