[RocketMQ 5.3.1] Win11 + Docker Desktop 本地部署全流程 + 踩坑记录

时间比较仓促,部署Linux的过程我就简写啦。

0. 我的系统版本(供参考)

Windows 11 专业版 24H2, Build 26100.2161

Experience: Windows Feature Experience Pack 1000.26100.32.0

JDK: OpenJDK Amazon Corretto 21.0.4.7.1

1. 在WSL2上安装Ubuntu 24.04

我完全参照了这个安装,流程上没啥问题:Install Ubuntu on WSL2 - Ubuntu WSL documentation

遇到的坑:

(1)安装之后需要以管理员身份打开。进入到命令行才算是安装完成。

(2)打开Ubuntu 24.04后无法进入命令行,显示WslRegisterDistribution failed with error: 0x80370114 后面跟着一堆问号或者啥

解决方法:控制面板→启用或关闭Windows功能→勾选 Hyper-V和Virtual Machine Platform,最好不要勾选Telnet→确定后重启电脑。

2. 安装Docker Desktop:Windows | Docker Docs

不需要付费,也不用登录,直接打开就行。遇到的坑:

(1)无法打开Docker Desktop,显示 An unexpected error was encountered while executing a WSL command...

解决方法:确认已安装的Linux子系统来自Ubuntu Distribution,并设置为默认。详见:https://stackoverflow.com/questions/76160943/docker-desktop-an-unexpected-error-was-encountered-while-executing-a-wsl-comma

3. 从Docker安装RocketMQ 5.3.1

在标题栏上搜索"rocketmq",然后直接 pull 即可。

4. 创建一个共享网络,并启动一个命名服务。

以管理员身份打开Powershell,然后执行

bash 复制代码
docker network create rocketmq

docker run -d --name rmqnamesrv -p 9876:9876 --network rocketmq apache/rocketmq:5.3.1 sh mqnamesrv

现在我们占用了 9876 这个端口。还可以顺便用这个命令检查一下是否正常启动了:

bash 复制代码
docker logs -f rmqnamesrv

当然,从Docker Desktop也能看:

5. 启用Broker和Proxy

官方步骤在这个:Run RocketMQ in Docker | RocketMQ

但是我的步骤和官网不太一样,可以先试试我的步骤

(1)随便找个地方新建个记事本,然后重命名为broker.conf,空文件就行,啥也不用写。我建在了 D:\broker.conf

(2)在Powershell中执行

bash 复制代码
docker run -d `
  --name rmqbroker `
  --network rocketmq `
  -p 10912:10912 -p 10911:10911 -p 10909:10909 `
  -p 8080:8080 -p 8081:8081 `
  -e "NAMESRV_ADDR=rmqnamesrv:9876" `
  -v /D/broker.conf:/home/rocketmq/rocketmq-5.3.1/conf/broker.conf `
  apache/rocketmq:5.3.1 sh mqbroker --enable-proxy `
  -c /home/rocketmq/rocketmq-5.3.1/conf/broker.conf

注意:-v后面推荐使用Unix风格的绝对路径,比如我的写成 /D/broker.conf,冒号后面的部分不用改。

10909、10911、10912三个端口都应该做映射(如命令所示)。现在我们能在容器列表看到:

6. 点进 rmqbroker,确认一下 broker.conf文件真实存在

依次展开:/home/rocketmq/rocketmq-5.3.1/conf/,看有没有 broker.conf 文件

7. 回到 Exec,执行以下命令,然后重启容器

bash 复制代码
cd /home/rocketmq/rocketmq-5.3.1/conf/

echo "brokerIP1=127.0.0.1" > broker.conf

重启容器:点击右上角那个圈圈箭头

8. 如果你想,可以手动建立一个Topic,也可以不建

这次我们在 Powershell 里进入容器,然后执行新建命令,就叫 TopicTest 吧,默认集群即可

bash 复制代码
docker exec -it rmqbroker sh

sh mqadmin updateTopic -n rmqnamesrv:9876 -t TopicTest

9. Java 代码验证一下

(0)POM

html 复制代码
<!-- https://mvnrepository.com/artifact/org.apache.rocketmq/rocketmq-client -->
<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-client</artifactId>
    <version>5.3.1</version>
</dependency>

(1)生产者

java 复制代码
package com.example.demo.rmq;

import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;

@SuppressWarnings("preview")
public class Producer {
    public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
        DefaultMQProducer producer = new DefaultMQProducer("ProducerGroup");
        producer.setNamesrvAddr("localhost:9876");
        producer.start();

        Message msg = new Message("TopicTest", "TagA", "Hello RocketMQ".getBytes());
        producer.send(msg, 10000);
        System.out.println(STR."Message sent: \{new String(msg.getBody())}");

        producer.shutdown();
    }
}

(2)消费者

java 复制代码
package com.example.demo.rmq;

import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.remoting.protocol.heartbeat.MessageModel;

@SuppressWarnings("preview")
public class Consumer {
    public static void main(String[] args) throws MQClientException {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroup");
        consumer.setNamesrvAddr("localhost:9876");
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);

        consumer.subscribe("TopicTest", "*");
        consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
            for (MessageExt msg : msgs) {
                System.out.println(STR."Received message: \{new String(msg.getBody())}");
            }
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        });

        consumer.setMessageModel(MessageModel.BROADCASTING);
        consumer.start();
    }
}

(3)删除 Topic

java 复制代码
package com.example.demo.rmq;

import org.apache.rocketmq.client.ClientConfig;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.impl.MQClientManager;
import org.apache.rocketmq.remoting.exception.RemotingException;

import java.util.concurrent.ExecutionException;

@SuppressWarnings("preview")
public class DeleteTopics {
    public static void main(String[] args) throws ExecutionException, InterruptedException, RemotingException, MQClientException {
        final String topicToDelete = "TopicTest";
        final String nameServerAddr = "localhost:9876";
        final String brokerAddr = "localhost:10911";

        ClientConfig config = new ClientConfig();
        config.setNamesrvAddr(nameServerAddr);

        var admin = MQClientManager.getInstance().getOrCreateMQClientInstance(config).getMQClientAPIImpl();
        admin.start();
        System.out.println(STR."Before deletion, topics available: \{admin.getTopicListFromNameServer(3000).getTopicList()}");

        // Step 1: Delete topic from NameServer
        admin.deleteTopicInNameServer(nameServerAddr, topicToDelete, 3000);

        // Step 2: Delete topic from Broker
        admin.deleteTopicInBroker(brokerAddr, topicToDelete, 3000);

        System.out.println(STR."After deletion, topics available: \{admin.getTopicListFromNameServer(3000).getTopicList()}");
    }
}

运行结果:

Before deletion, topics available: [RMQ_SYS_TRANS_HALF_TOPIC, BenchmarkTest, OFFSET_MOVED_EVENT, TBW102, %RETRY%ConsumerGroup, rmq_sys_REVIVE_LOG_DefaultCluster, SELF_TEST_TOPIC, DefaultCluster, SCHEDULE_TOPIC_XXXX, DefaultCluster_REPLY_TOPIC, rmq_sys_wheel_timer, 6d472f2c2a3d, rmq_sys_SYNC_BROKER_MEMBER_6d472f2c2a3d, RMQ_SYS_TRANS_OP_HALF_TOPIC, TopicTest]

After deletion, topics available: [RMQ_SYS_TRANS_HALF_TOPIC, BenchmarkTest, OFFSET_MOVED_EVENT, TBW102, %RETRY%ConsumerGroup, rmq_sys_REVIVE_LOG_DefaultCluster, SELF_TEST_TOPIC, DefaultCluster, SCHEDULE_TOPIC_XXXX, DefaultCluster_REPLY_TOPIC, rmq_sys_wheel_timer, 6d472f2c2a3d, rmq_sys_SYNC_BROKER_MEMBER_6d472f2c2a3d, RMQ_SYS_TRANS_OP_HALF_TOPIC]

可以发现末尾的 TopicTest 已经删掉了。

That's it.


后记:在最新版本的 RocketMQ 中,已经没有 DefaultMQAdminExt 等常用的 Admin 类了,都需要通过 ClientConfig 构建 MQClient,不知道为何官方文档迟迟没有更新。另外,已经不需要 DeleteTopicRequestHeader 等麻烦的类了。

其他内容欢迎大家补充。

相关推荐
RemainderTime5 天前
(七)Spring Cloud Alibaba 2023.x:RocketMQ 消息队列配置与实现
后端·spring cloud·微服务·rocketmq
你啊我啊你好5 天前
常用的消息中间件(ActiveMQ、RabbitMQ、RocketMQ、Kafka)面试精华
rabbitmq·rocketmq·activemq
Hello-Brand6 天前
RocketMQ系列3:核心技术介绍
消息队列·rabbitmq·rocketmq·mq·消息中间件·削峰填谷
_BugMan6 天前
【业务场景】订单超时取消的各种方案
redis·java-ee·rocketmq
Ch.yang10 天前
【架构】从 Socket 的角度认识非阻塞模型
tomcat·rocketmq
码农老起10 天前
从RocketMQ到Dubbo:自研中间件技术的崛起
中间件·dubbo·rocketmq
Steven_Mmm12 天前
关于消息队列性能是否能接收 5 万个 MQ
kafka·rocketmq
小范馆12 天前
RocketMQ面试题合集
java·rocketmq·java-rocketmq
菜菜-plus13 天前
Kafka | RabbitMQ | RocketMQ | ActiveMQ 的区别和入门案例
kafka·rabbitmq·rocketmq
Hello-Brand16 天前
RocketMQ系列2:领域模型和技术概念
消息队列·rocketmq·消息中间件