在 Windows Docker 上搭建 RocketMQ 单节点集群并解决常见连接与发送问题的实战经验分享
:本文基于笔者在 Windows 环境下使用 Docker 搭建 Apache RocketMQ 4.4.0 的个人实践经验撰写。RocketMQ 作为一款优秀的分布式消息队列中间件,在高并发、低延迟场景下表现出色,但其在 Docker 容器化部署中的网络配置往往会让初学者感到困惑。本文并非官方教程,仅记录了笔者从环境准备到问题解决的全过程,旨在为遇到类似问题的朋友提供参考。如果文中有所疏漏或不准确之处,欢迎读者指正。感谢 RocketMQ 社区和相关博客的启发(如 CSDN 上关于多网卡 IP 配置的文章),让我们共同学习。
1. 引言:为什么选择 RocketMQ?
Apache RocketMQ 是一款由阿里巴巴开源并捐献给 Apache 基金会的分布式消息队列,支持高吞吐、低延迟、可靠的消息传递,适用于微服务解耦、事件驱动架构等场景。在本地开发测试时,使用 Docker 快速搭建单节点集群是最便捷的方式。然而,在 Windows 平台下,Docker 的虚拟网络适配器(如 vEthernet)和多网卡环境容易导致 Broker 注册 IP 不一致、客户端连接超时等问题。
本文聚焦于:
Windows Docker 环境下的 RocketMQ 部署。
解决 Dashboard 连接失败、Java 客户端发送状态为 SLAVE_NOT_AVAILABLE 等常见坑。
通过日志分析和配置调整,实现完整链路验证。
环境版本:
OS: Windows 10(带 Docker Desktop)。
Docker: 最新版(启用 WSL 2 后端)。
RocketMQ: 4.4.0(镜像 rocketmqinc/rocketmq)。
Dashboard: apacherocketmq/rocketmq-dashboard:latest。
Java 客户端: rocketmq-client 4.4.0。
2. 环境准备
2.1 安装 Docker Desktop
下载并安装 Docker Desktop(官网:https://www.docker.com/products/docker-desktop)。
启用 WSL 2 后端(设置 > General > Use the WSL 2 based engine)。
创建自定义网络:
docker network create rocketmq(用于容器间通信)。
2.2 准备配置文件和目录
在宿主机创建目录,例如 D:/04-ProgramFiles/Docker/rocketmq/:
conf/broker.conf:Broker 配置(详见后文)。data/logs和data/store:持久化日志和消息存储(避免容器重启数据丢失)。
2.3 查看宿主机网络适配器
运行 ipconfig 获取 IP:
重点关注
vEthernet (Default Switch)的 IPv4(如 172.26.16.1),这是 Docker 容器访问宿主机的桥接 IP。其他如物理网卡(172.20.x.x)或 VMware 虚拟网卡(192.168.x.x)可能干扰,需避免。
3. 部署步骤
3.1 启动 NameServer
NameServer 是 RocketMQ 的注册中心。
docker run -d --network rocketmq --name rmqnamesrv -p 9876:9876 rocketmqinc/rocketmq sh mqnamesrv检查日志:
docker logs rmqnamesrv(应无错误)。
3.2 配置并启动 Broker
broker.conf 内容(关键配置,后文解释):
brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 0
deleteWhen = 04
fileReservedTime = 72
brokerRole = SYNC_MASTER # 单节点推荐 SYNC_MASTER,避免 SLAVE_NOT_AVAILABLE
flushDiskType = ASYNC_FLUSH
autoCreateTopicEnable = true
namesrvAddr = rmqnamesrv:9876
brokerIP1 = 172.26.16.1 # 宿主机 Docker Default Switch IP,用于注册和客户端访问
brokerIP2 = 172.26.16.1 # 用于主从复制通道(即使单节点,也可强化 HA 检查)
启动命令:
docker run -d -p 10909:10909 -p 10911:10911 --network rocketmq --name rmqbroker \
-v D:/04-ProgramFiles/Docker/rocketmq/data/logs:/opt/rocketmq-4.4.0/log \
-v D:/04-ProgramFiles/Docker/rocketmq/data/store:/opt/rocketmq-4.4.0/store \
-v D:/04-ProgramFiles/Docker/rocketmq/conf/broker.conf:/opt/rocketmq-4.4.0/conf/broker.conf \
-e "NAMESRV_ADDR=rmqnamesrv:9876" rocketmqinc/rocketmq sh mqbroker -c /opt/rocketmq-4.4.0/conf/broker.conf
日志检查:
docker logs rmqbroker应显示 "The broker[...] boot success",并指定 brokerIP1。
3.3 启动 Dashboard
Dashboard 用于可视化监控。
docker run -d --network rocketmq --name rmq-dashboard -p 8080:8082 \
-e "NAMESRV_ADDR=rmqnamesrv:9876" apacherocketmq/rocketmq-dashboard:latest
浏览器访问 http://localhost:8080,连接 NameServer: rmqnamesrv:9876。
3.4 验证集群
mqadmin 工具(从 rocketmq-all-4.4.0-bin-release 下载,进入 bin 目录):
mqadmin clusterList -n 127.0.0.1:9876输出应显示 broker-a Addr 为 172.26.16.1:10911。
Dashboard:Cluster 页面显示 Broker 信息。
4. 常见问题及解决方案
4.1 Dashboard 显示 "connect to null failed" 或 Broker 未注册
原因:Broker 默认使用容器内部 IP(127.0.0.1 或 172.18.x.x)注册到 NameServer,导致 Dashboard(同网络)无法路由。 解决方案:
设置 brokerIP1 为宿主机 Docker Default Switch IP(通过 ipconfig 获取)。
重启 Broker,观察日志确认注册 IP。
备选:如果失败,尝试物理网卡 IP,但优先 Default Switch(Docker 桥接优化)。
4.2 Java 客户端连接超时或路由为 127.0.0.1
客户端代码示例(Spring Boot 测试):
DefaultMQProducer producer = new DefaultMQProducer("test-producer-group");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.setVipChannelEnabled(false); // 禁用 VIP 通道,避免 10909 端口问题
producer.start();
Message msg = new Message("testTopic", "Hello RocketMQ!".getBytes());
SendResult result = producer.send(msg);
System.out.println("发送状态: " + result.getSendStatus());
producer.shutdown();原因:路由 IP 不一致。 解决方案:
确保 Broker brokerIP1 正确。
添加
producer.setVipChannelEnabled(false)和路由打印:List<MessageQueue> queues = producer.fetchPublishMessageQueues("testTopic");
System.out.println("路由: " + queues);JVM 参数:
-Djava.net.preferIPv4Stack=true避免 IPv6 干扰。
4.3 发送状态 SLAVE_NOT_AVAILABLE
原因:
默认 ASYNC_MASTER 模式下,客户端检查 Slave 可用性。即使单节点,无 Slave 也会返回此警告(参考:)。
即使消息已写入(Dashboard Produce Count +1),状态仍降级。 解决方案:
单节点时切换
brokerRole = SYNC_MASTER(同步模式跳过 Slave 检查)。设置 brokerIP2 与 brokerIP1 一致,确保 HA 复制通道 IP 统一(参考:))。
4.4 Dashboard Broker NO. 显示 0(undefined)
原因:Dashboard 解析心跳时角色标签不明确(版本兼容)。 解决方案:忽略(不影响功能),或重启后等待心跳刷新;mqadmin clusterList 可确认 "Master" 角色。
5. 全链路验证:生产消费测试
生产者:如上代码,状态 SEND_OK。
消费者:
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("test-consumer-group");
consumer.setNamesrvAddr("127.0.0.1:9876");
consumer.subscribe("testTopic", "*");
consumer.registerMessageListener((msgs, context) -> {
System.out.println("收到: " + new String(msgs.get(0).getBody()));
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
consumer.start();
Thread.sleep(30000);
consumer.shutdown();Dashboard:观察 TPS 和 Count 变化。
7. 总结与注意事项
通过上述步骤,您可以在 Windows Docker 上快速搭建 RocketMQ 并解决网络相关痛点。关键在于理解 Docker 桥接 IP 和 RocketMQ 的注册/复制机制。生产环境建议:
使用 RocketMQ 5.x(DLedger 模式更简)。
监控防火墙、持久化卷备份。
- 微信
- 赶快加我聊天吧

- 赶快加我聊天吧
