【RocketMq】 #rocketmq RocketMq 4.9.4 Windows-docker 部署
引言
注意个人使用了4.9.4的Rocketmq版本进行学习部署使用。因为windows上使用docker部署不同版本的RockerMq可能会有不同的情况,这里仅保证4.9.4的版本可以正确运行。
Windows 配置上要比Linux 配置麻烦一些,尤其是复制路径需要把反斜杠换成斜杠。
个人环境
- CPU:12代英特尔12700
- 内存 32G
- 操作系统:Win11 21H(12代英特尔大小核优化,没办法)
- RocketMq:4.9.4 版本
- Docker:官网当时能下到的最新版
- 镜像:官方提供的4.9.4的打包镜像,非用户二次打包
基础配置
WSL安装
Docker在Win11里面存在一些其他问题,一上来启动的时候Docker会要求安装WSL。
- 安装Docker这一步直接去官网找最新版本下载安装即可,这里略过截图了。
- 个人使用的Win11,发现报错需要升级WSL,如果没有的话可以忽略,如果出现类似报错的话,看如下链接:旧版 WSL 的手动安装步骤 | Microsoft Learn
- 通过上面的链接修复WSL的版本问题之后,重启Docker,可以正常使用Docker了。
介绍:安装 WSL | Microsoft Learn
本指南将介绍如何使用适用于 Linux 的 Windows 子系统安装 Linux 发行版(例如 Ubuntu、OpenSUSE、Kali、Debian、Arch Linux 等)。 通过 WSL,你可使用与 Windows 工具(如 PowerShell 或 Visual Studio Code)完全集成的 Linux 工具(如 Bash 或 Grep),而无需双启动。
这里简单描述个人的修复步骤:
使用管理员运行CMD,然后执行下面的命令,如果提示如图说明操作成功
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
Deployment Image Servicing and Management tool
Version: 10.0.22000.653
Image Version: 10.0.22000.1098
Enabling feature(s)
[==========================100.0%==========================]
The operation completed successfully.
下载Linux内核包
将 WSL 2 设置为默认版本
wsl --set-default-version 2
这样处理之后Windows Docker 就可以正常启动了,可以看到比Linux和Mac都要麻烦不少。
- 拉取Docker的Rocketmq镜像之前需要在自己定义的目录执行下面的命令提前确定好RocketMq的日志以及持久化文件存储位置,因为这里借用了Git Bash的命令行工具,所以命令使用的是Linux的相关命令(比较建议使用这个小技巧)。
# 所在目录 /d/adongstack/run/docker/rocketmq
$ mkdir -p ./data/namesrv/logs~
# 所在目录 /d/adongstack/run/docker/rocketmq
$ mkdir -p ./data/broker/conf
# 所在目录/d/adongstack/run/docker/rocketmq
$ mkdir -p ./data/broker/logs
# 所在目录 /d/adongstack/run/docker/rocketmq
$ mkdir -p ./data/broker/store
上方奇怪的路径显示来自:powershell
- 此外在正式拉取镜像之前也可以先把Docker的拉取镜像仓库换一下,这里个人第一次拉取的速度比较快所以没有换。
![[国内镜像仓库.png]]
注意JSON的格式,如果图方便把下面这一段代码完全复制然后贴进去即可,或者只追加"registry-mirrors" 部分。
{
"builder": {
"gc": {
"defaultKeepStorage": "20GB",
"enabled": true
}
},
"experimental": false,
"features": {
"buildkit": true
},
// 下面为追加内容(本行复制后请删除)
"registry-mirrors": [
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com"
]
}
Docker Namesrv 配置
- 一切准备工作做好,我们开始拉取docker镜像,然后进行启动测试,配置使用默认的即可,下面拉取rocketmq 4.9.4 的镜像命令:
$ docker pull apache/rocketmq:4.9.4
4.9.4: Pulling from apache/rocketmq
.... 省略一些内容
Status: Downloaded newer image for apache/rocketmq:4.9.4
# 下面的结果说明拉取成功了
docker.io/apache/rocketmq:4.9.4
如果结尾出现类似的信息说明拉取成功。下面开始运行镜像,Docker Window 提供可视化的配置界面,但是我觉得命令的方式快很多,这里仅仅截图展示一下。
![[默认启动docker配置.png]]
下面介绍命令的方式启动关键组件。
- 准备namesrv的数据存储和日志存储地址。
D:/adongstack/run/docker/rocketmq/data/namesrv/logs
D:/adongstack/run/docker/rocketmq/data/namesrv/stores
然后准备构建namesrv的命令,注意修改两个-V 的地址:
网上有很多日志在/root/logs
下面的,个人实际使用的情况和此情况不符合
docker run -d \
--restart=always \
--name rmqnamesrv \
-p 9876:9876 \
-v D:/adongstack/run/docker/rocketmq/data/namesrv/logs:/home/rocketmq/logs \
-v D:/adongstack/run/docker/rocketmq/data/namesrv/stores:/home/rocketmq/store \
-e "MAX_POSSIBLE_HEAP=100000000" \
apache/rocketmq:4.9.4 \
sh mqnamesrv
注意映射原始地址,一个是 logs,另一个是 store,为了确认是否映射正确,可以进入docker exec -it '镜像地址'
的方式进入到镜像的根目录,然后一层层网上找到对应的原始地址(此时也可以发现Store 目录也是空的)
相关的参数作用如下:
参数 | 作用 |
---|---|
-d | 守护进程启动 |
--restart=always | docker重启时候容器自动重启 |
--name rmqnamesrv | 把容器的名字设置为rmqnamesrv |
-p 9876:9876 | 端口号配置,格式:容器的端口号:宿主机的端口号 |
-v xxxx/namesrv/logs:/home/rocketmq/logs | 把容器内的/home/rocketmq/logs日志目录挂载到宿主机的自定义路径目录(注意win需要带盘符) |
-v xxxx/namesrc/store:/home/rocketmq/store | 把容器内的/home/rocketmq/store 数据存储目录挂载到宿主机的自定义路径目录(注意win需要带盘符) |
rmqnamesrv | 容器的名字 |
-e “MAX_POSSIBLE_HEAP=100000000” | 该容器的最大堆内存为100000000,基本为无限大 |
apache/rocketmq:4.9.4 | 使用的镜像名称,比如这里使用了官方4.9.4的镜像 |
sh mqnamesrv | 启动namesrv服务 |
运行之后通常会返回一个唯一ID比如$ 53d8bdda518f1a4ed24a45c7c66a463413933d04ee7b6e5ac7a9150dea54ca48
,之后可以立即检查本地映射的目录是否存在对应的日志文件,注意因为此时刚刚启动store目录的内容是空的。
Docker Broker 配置
- 同理首先确定broker的配置文件以及日志的存储位置,还有数据文件的存储位置,个人的配置路径如下:
D:/adongstack/run/docker/rocketmq/data/broker/logs
D:/adongstack/run/docker/rocketmq/data/broker/conf
D:/adongstack/run/docker/rocketmq/data/broker/stores
- 配置broker的核心配置
broker.conf
,这个配置的内容摘自官方源码的文件,底部新增了自定义的配置。
# mq集群名称,注意这里进行了更改
brokerClusterName = YYDSCluster
#broker名称,master和slave使用相同的名称,表明他们的主从关系
brokerName = broker-master
#0表示Master,大于0表示不同的slave
brokerId = 0
#表示几点做消息删除动作,默认是凌晨4点
deleteWhen = 00
#在磁盘上保留消息的时长,单位是小时
fileReservedTime = 72
#有三个值:SYNC_MASTER,ASYNC_MASTER,SLAVE;同步和异步表示Master和Slave之间同步数据的机制;
brokerRole = ASYNC_MASTER
#刷盘策略,取值为:ASYNC_FLUSH,SYNC_FLUSH表示同步刷盘和异步刷盘;SYNC_FLUSH消息写入磁盘后才返回成功状态,ASYNC_FLUSH不需要;
flushDiskType = ASYNC_FLUSH
#设置broker节点所在服务器的ip地址(公网IP),win系统下,用ipconfig查一下你的主机ip
brokerIP1 = 192.168.0.107
# 是否允许 Broker 自动创建 Topic,建议线下开启,线上关闭 !!!这里仔细看是 false,false,false
autoCreateTopicEnable=true
# 是否允许 Broker 自动创建订阅组,建议线下开启,线上关闭
autoCreateSubscriptionGroup=true
# Broker 对外服务的监听端口
listenPort=10911
#补充
# 磁盘使用达到95%之后,生产者再写入消息会报错 CODE: 14 DESC: service not available now, maybe disk full diskMaxUsedSpaceRatio=95
- 把配置文件放到最开始定义的路径
D:/adongstack/run/docker/rocketmq/data/broker/conf
当中。
提醒 NameServer启动之后的RocketMq根路径为:/home/rocketmq/rocketmq-4.9.4/con
,Broker同理。
接着是构建Broker,个人起初参考了网上的博客文章,结果发现构建出来均出现找不到conf的问题。
.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at org.apache.rocketmq.broker.BrokerStartup.createBrokerController(BrokerStartup.java:119)
at org.apache.rocketmq.broker.BrokerStartup.main(BrokerStartup.java:57)
毫无疑问是个人尝试的命令出错了,在经过反复尝试之后修复,注意rocketmq的home目录为: /home/rocketmq/rocketmq-4.9.4
docker run -d \
--restart=always \
--name rmqbroker \
--link rmqnamesrv:namesrv \
-p 10911:10911 \
-p 10909:10909 \
-v D:/adongstack/run/docker/rocketmq/data/broker/log:/home/rocketmq/logs \
-v D:/adongstack/run/docker/rocketmq/data/broker/store:/home/rocketmq/store \
-v D:/adongstack/run/docker/rocketmq/data/broker/conf/broker.conf:/home/rocketmq/rocketmq-4.9.4/conf/broker.conf \
-e "NAMESRV_ADDR=namesrv:9876" \
-e "MAX_POSSIBLE_HEAP=200000000" \
apache/rocketmq:4.9.4 \
sh mqbroker -c ../conf/broker.conf
这里有一个踩坑点是最后一条命令sh mqbroker -c ../conf/broker.conf
,个人尝试替换为/home/rocketmq/rocketmq-4.9.4/conf/broker.conf
是无效并且报错的,此外这里需要特别注意一定要自定义broker.conf
启动,否则默认情况下broker默认走Docker内网会导致我们的访问变成外部访问而访问不到。
不管是Linux还是Windows,都需要确保启动rocketmq的用户是具备目录操作权限的。windows通常没这个烦恼,但如果是Linux则本地 logs 目录一定要是 777 权限。
参数配置的作用如下:
参数 | 作用 |
---|---|
-d | 守护进程的方式启动 |
--restart=always | docker重启时候镜像自动重启 |
--name rmqbroker | 容器的名字设置为rmqbroker |
-link rmqnamesrv:namesrv | 和rmqnamesrv容器通信,rmqnamesrv代表本身的link名称,namesrv 表示 |
-p 10911:10911 | 把容器的非vip通道端口挂载到宿主机 |
-p 10909:10909 | 把容器的vip通道端口挂载到宿主机 |
-e “NAMESRV_ADDR=namesrv:9876” | 指定namesrv的地址为本机namesrv的ip地址:9876 |
-e “MAX_POSSIBLE_HEAP=200000000” rocketmqinc/rocketmq sh mqbroker | 指定broker服务的最大堆内存,本次指定为200000000 |
apache/rocketmq:4.9.4 | 使用的镜像名称 |
sh mqbroker -c ../broker.conf | 指定配置文件启动broker节点 |
启动完成之后,第一时间检查一下本地的映射目录和对应的容器内部文件是否正确进行映射。
Docker Dashboard 配置
在当前的版本中,可视化界面被更名为dashboard并且被移到了一个新项目当中,具体可以看下面的链接:
Notice: Console has renamed to dashboard and transfered the new repo, it will graduate in the near future, and welcome you to fill in the user due diligence.
这里按照文档的quick start
进行拉取:
docker pull apacherocketmq/rocketmq-dashboard:latest
注意提示的最低版本以及配置要求:
#### Prerequisite
1. 64bit OS, Linux/Unix/Mac is recommended;
2. 64bit JDK 1.8+;
3. Maven 3.2.x;
拉取之后Docker的内容如下:
![[RocketMq-docker可视化界面.png]]
接着我们使用下面的命令启动可视化界面,注意要改成宿主机 Ip 和 端口号(也就是自己的Windows电脑联网对应的IP,以太网或者Wifi):
docker run -d \
--name rocketmq-dashboard \
-e "JAVA_OPTS=-Drocketmq.namesrv.addr=192.168.0.107:9876" \
-p 18080:8080 \
-t apacherocketmq/rocketmq-dashboard:latest
启动之后,访问地址`http://localhost:18080(这里修改了宿主机的映射端口18080)。进入主页之后的内容如下:
![[Rocketmq可视化界面主页.png]]
到此就可以开心愉快的玩耍了。
踩坑点
虽然整个配置过程看起来很简单,但是如果不注意细节的话实际上有不少的踩坑点,这里一一叙述:
映射路径问题
网上映射的路径千奇百怪的,这里拿官方镜像映射发现路径如下:
/home/rocketmq/logs
/home/rocketmq/store
/home/rocketmq/rocketmq-4.9.4/conf/broker.conf
需要注意这些路径一个字母都不能错,否则启动是不会报错的,但是会出现你在映射路径的修改无法影响到整个容器的配置。
Producer查询问题
老生常谈的问题,解决办法是在自己本地测试的时候不要调用producer.shutdown()
方法(线上不能这么干),因为这个方法会在发送完成之后直接删除生产者组。
另外我想吐槽一下这个提示的用户体验是认真的么,带鱼屏看这种页面怕不是脖子都要甩断了(虽然我不是)。
此外这一堆报错看着也比较瘆得慌。
DashBoard 端口问题
dashboard用的是SpringBoot默认的8080端口,容易和自己的项目冲突,所以建议启动容器的时候映射到18080,可以避免端口占用的烦恼。
实验
下面简单做一个测试,为了追求快速,这里把快速拉取一个SpringBoot、pom.xml引用等过程跳过了,直接上代码。
注意 Broker 启动的时候配置文件指定了自动创建topic以及自动创建订阅组,所以不需要再用RocketMq的命令去创建队列,当然是自己学习的时候可以这样干,生产是不能开启的,切记!!!
autoCreateSubscriptionGroup=true
autoCreateTopicEnable=true
public static void main(String[] args) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
DefaultMQProducer producer = new DefaultMQProducer("test");
// 自己的本机IP
producer.setNamesrvAddr(Const.NAMESRV_ADDR_SINGLE);
producer.start();
for(int i = 0 ; i <1; i ++) {
// 1. 创建消息
Message message = new Message("test", // 主题
"TagA", // 标签
"key" + i, // 用户自定义的key ,唯一的标识
("Hello RocketMQ" + i).getBytes()); // 消息内容实体(byte[])
SendResult sr = producer.send(message, new MessageQueueSelector() {
@Override
public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
Integer queueNumber = (Integer)arg;
return mqs.get(queueNumber);
}
}, 2);
System.err.println(sr);
// 自己做实验需要关掉,否则会自动删除生产者组
// producer.shutdown();
}
最后到Producer去查询,成功看到内容:
小结
下面是个人在另一台Windows电脑上的执行成功的脚本:
# 启动 NameServ
docker run -d \
--restart=always \
--name rmqnamesrv \
-p 9876:9876 \
-v E:/adongstack/run/docker/rocketmq/data/namesrv/logs:/home/rocketmq/logs \
-v E:/adongstack/run/docker/rocketmq/data/namesrv/store:/home/rocketmq/store \
-e "MAX_POSSIBLE_HEAP=100000000" \
apache/rocketmq:4.9.4 \
sh mqnamesrv
# 启动 Broker
docker run -d \
--restart=always \
--name rmqbroker \
--link rmqnamesrv:namesrv \
-p 10911:10911 \
-p 10909:10909 \
-v E:/adongstack/run/docker/rocketmq/data/broker/logs:/home/rocketmq/logs \
-v E:/adongstack/run/docker/rocketmq/data/broker/store:/home/rocketmq/store \
-v E:/adongstack/run/docker/rocketmq/data/broker/conf/broker.conf:/home/rocketmq/rocketmq-4.9.4/conf/broker.conf \
-e "NAMESRV_ADDR=namesrv:9876" \
-e "MAX_POSSIBLE_HEAP=200000000" \
apache/rocketmq:4.9.4 \
sh mqbroker -c ../conf/broker.conf
# docker-dashboard 启动命令
docker run -d
--name rocketmq-dashboard
-e "JAVA_OPTS=-Drocketmq.namesrv.addr=本机电脑IP:9876" -p 18080:8080 -t apacherocketmq/rocketmq-dashboard:latest
总结
总得来说需要格外小心Broker的配置,一定要自定义配置并且定义宿主机的IP,建议有条件使用Linux部署docker和使用Docker。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。