保姆级教程:手把手教你用RocketMQ 5.x + Docker Compose搭建带Console的完整测试环境

张开发
2026/4/18 12:20:25 15 分钟阅读

分享文章

保姆级教程:手把手教你用RocketMQ 5.x + Docker Compose搭建带Console的完整测试环境
从零构建RocketMQ 5.x全栈测试环境Docker Compose实战指南在分布式系统开发中消息队列如同血管般串联起各个服务组件。而RocketMQ作为阿里巴巴开源的分布式消息中间件凭借其高吞吐、低延迟和金融级稳定性的特点已成为企业级应用的首选之一。但许多开发者在初次接触RocketMQ时往往会在测试环境搭建这一步就遇到各种坑——从控制台看不到生产消费组到容器网络配置不当导致的通信失败。本文将彻底解决这些问题带你用Docker Compose构建一个包含NameServer、Broker集群和可视化Console的完整RocketMQ 5.x测试环境并编写符合生产环境标准的测试代码。1. 环境规划与架构设计在动手编写docker-compose.yml之前我们需要先明确测试环境的拓扑结构。一个健壮的RocketMQ测试环境至少应包含NameServer集群RocketMQ的服务发现核心建议至少部署两个节点实现高可用Broker主从节点采用异步复制模式主节点处理写请求从节点提供读容灾Console服务官方提供的Web管理界面用于监控Topic、消费组等关键指标网络隔离为容器创建专属网络避免端口冲突以下是推荐的资源分配方案组件实例数内存端口映射数据卷NameServer2512MB9876:9876-Broker Master11GB10909:10909, 10911-10912:同左./broker/logsBroker Slave11GB11909:11909, 11911-11912:同左./slave/logsConsole1512MB8080:8080./console/config提示生产环境需要根据消息吞吐量调整Broker内存测试环境1GB足够应对常规场景2. Docker Compose编排实战现在让我们编写完整的docker-compose.yml文件。这里使用RocketMQ 5.1.1版本所有镜像均来自官方仓库version: 3.8 services: namesrv1: image: apache/rocketmq:5.1.1 container_name: rmqnamesrv1 command: sh mqnamesrv ports: - 9876:9876 volumes: - ./namesrv1/logs:/home/rocketmq/logs networks: - rmqnet namesrv2: image: apache/rocketmq:5.1.1 container_name: rmqnamesrv2 command: sh mqnamesrv ports: - 9877:9876 volumes: - ./namesrv2/logs:/home/rocketmq/logs networks: - rmqnet broker-master: image: apache/rocketmq:5.1.1 container_name: rmqbroker-master command: sh mqbroker -c /home/rocketmq/conf/broker.conf ports: - 10909:10909 - 10911:10911 - 10912:10912 volumes: - ./broker/conf:/home/rocketmq/conf - ./broker/logs:/home/rocketmq/logs - ./broker/store:/home/rocketmq/store environment: - NAMESRV_ADDRnamesrv1:9876;namesrv2:9876 depends_on: - namesrv1 - namesrv2 networks: - rmqnet broker-slave: image: apache/rocketmq:5.1.1 container_name: rmqbroker-slave command: sh mqbroker -c /home/rocketmq/conf/broker-slave.conf ports: - 11909:11909 - 11911:11911 - 11912:11912 volumes: - ./slave/conf:/home/rocketmq/conf - ./slave/logs:/home/rocketmq/logs - ./slave/store:/home/rocketmq/store environment: - NAMESRV_ADDRnamesrv1:9876;namesrv2:9876 depends_on: - broker-master networks: - rmqnet console: image: apacherocketmq/rocketmq-console:2.0.0 container_name: rmqconsole ports: - 8080:8080 environment: - JAVA_OPTS-Drocketmq.config.namesrvAddrnamesrv1:9876;namesrv2:9876 depends_on: - namesrv1 networks: - rmqnet networks: rmqnet: driver: bridge关键配置说明Broker主从配置需要在volumes映射的conf目录下创建broker.conf和broker-slave.conf网络隔离所有服务接入rmqnet专用网络容器间通过服务名通信数据持久化将日志和存储目录映射到宿主机避免容器重启数据丢失Broker主节点配置文件示例./broker/conf/broker.confbrokerClusterName DefaultCluster brokerName broker-a brokerId 0 deleteWhen 04 fileReservedTime 48 brokerRole SYNC_MASTER flushDiskType ASYNC_FLUSH brokerIP1 broker-master3. 控制台友好的测试代码编写许多教程使用临时Producer Group导致控制台无法持续监控。下面展示如何编写符合生产标准的测试代码public class StableProducer { private static final String NAMESRV_ADDR localhost:9876; private static final String PRODUCER_GROUP PERF_TEST_GROUP; private static final String TOPIC BENCHMARK_TOPIC; public static void main(String[] args) throws Exception { // 初始化生产者使用有意义的Group名称 DefaultMQProducer producer new DefaultMQProducer(PRODUCER_GROUP); producer.setNamesrvAddr(NAMESRV_ADDR); producer.start(); // 注册JVM关闭钩子确保优雅退出 Runtime.getRuntime().addShutdownHook(new Thread(() - { System.out.println(Shutting down producer...); producer.shutdown(); })); // 持续发送消息保持长连接 while (true) { try { Message msg new Message(TOPIC, TagA, OrderID188, Hello RocketMQ.getBytes(RemotingHelper.DEFAULT_CHARSET)); SendResult sendResult producer.send(msg); System.out.printf(%s%n, sendResult); Thread.sleep(1000); // 控制发送频率 } catch (Exception e) { e.printStackTrace(); Thread.sleep(5000); } } } }这段代码实现了稳定的生产者组使用明确命名的PRODUCER_GROUP而非默认值长连接保持通过无限循环维持生产者与Broker的连接优雅关闭注册ShutdownHook确保进程退出时正确注销生产者组异常处理捕获并处理发送异常避免进程意外终止对应的消费者代码同样需要注意这些要点public class StableConsumer { private static final String NAMESRV_ADDR localhost:9876; private static final String CONSUMER_GROUP PERF_CONSUMER_GROUP; private static final String TOPIC BENCHMARK_TOPIC; public static void main(String[] args) throws Exception { DefaultMQPushConsumer consumer new DefaultMQPushConsumer(CONSUMER_GROUP); consumer.setNamesrvAddr(NAMESRV_ADDR); consumer.subscribe(TOPIC, *); consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) - { System.out.printf(%s Receive New Messages: %s %n, Thread.currentThread().getName(), msgs); return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; }); consumer.start(); System.out.println(Consumer Started.); // 保持进程运行 CountDownLatch latch new CountDownLatch(1); latch.await(); } }4. 环境验证与问题排查启动所有服务后按以下步骤验证环境检查容器状态docker-compose ps应看到所有服务状态为Up访问控制台 打开浏览器访问http://localhost:8080应看到RocketMQ控制台首页验证生产消费组可见性运行前面编写的测试代码在控制台Consumer和Producer标签页应能看到对应的组在Topic标签页应能看到消息堆积情况常见问题解决方案控制台无法连接NameServer# 检查Console容器的环境变量 docker exec -it rmqconsole env | grep namesrvAddr # 验证网络连通性 docker exec -it rmqconsole ping namesrv1Broker启动失败# 查看Broker日志 docker logs -f rmqbroker-master # 检查配置文件是否正确挂载 docker exec -it rmqbroker-master ls /home/rocketmq/conf生产者发送超时// 在代码中增加超时设置 producer.setSendMsgTimeout(60000); // 60秒超时5. 进阶配置与优化建议为了让测试环境更接近生产环境可以考虑以下优化Broker参数调优# 在broker.conf中添加 maxMessageSize5242880 # 提高单条消息大小限制至5MB flushInterval1000 # 刷盘间隔(ms)控制台安全配置# 启动Console时添加认证参数 environment: - JAVA_OPTS-Drocketmq.config.loginRequiredtrue -Drocketmq.config.accessKeyadmin -Drocketmq.config.secretKey123456资源限制# 在docker-compose.yml中为Broker设置资源限制 deploy: resources: limits: cpus: 2 memory: 2G reservations: memory: 1G日志收集方案# 添加ELK服务收集RocketMQ日志 services: filebeat: image: docker.elastic.co/beats/filebeat:8.3.2 volumes: - ./broker/logs:/var/log/rocketmq - ./filebeat.yml:/usr/share/filebeat/filebeat.yml depends_on: - elasticsearch这套环境已经过多次实践验证能够稳定支持消息收发测试、流量压测等场景。我在金融项目中使用类似配置处理过日均亿级消息最关键的是保持Producer Group的稳定性避免使用临时组名导致监控断点。

更多文章