RocketMQ 5.x 集群部署实战:3 台机器搞定 2 主 2 从,Docker Host 模式一把梭

网上大部分 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 台机器配成集群这事,第二次做就不想再踩一遍坑了。

相关推荐
http阿拉丁神猫1 小时前
kubernetes知识点汇总19~24
云原生·容器·kubernetes
春日见2 小时前
UniAD的逻辑,与传统自动驾驶的差异
人工智能·windows·git·机器学习·docker·容器·自动驾驶
乐观的Terry2 小时前
Docker 部署 RocketMQ 5.1.0 踩坑实录:从超时到 Console 连不上的完整解决之路
docker·容器·rocketmq
切糕师学AI2 小时前
K8s中的控制器模式(Controller Pattern)
容器·kubernetes
sanyii3131312 小时前
k8s工作负载-Deployment的参数与灰度发布
云原生·容器·kubernetes
道清茗2 小时前
【Kubernetes知识点问答题】常规维护管理操作 / ETCD 备份与恢复
docker·kubernetes·etcd
lpruoyu2 小时前
【云原生】Kubernetes平台存储系统搭建_CRI、CNI、CSI
ceph·云原生·容器·kubernetes
不爱学英文的码字机器2 小时前
Apache RocketMQ+cpolar 让消息服务全网可达
apache·rocketmq
面对疾风叭!哈撒给3 小时前
Linux之docker-compose使用(redis、nginx、tdengine、java应用)
linux·redis·docker