跳至主要內容

使用 Docker 和 docker-compose 快速部署 RocketMQ 集群 双主 / DLedger

Scarb大约 9 分钟

原文地址:http://hscarb.github.io/rocketmq/20220724-rocketmq-docker-compose.htmlopen in new window

使用 Docker 和 docker-compose 快速部署 RocketMQ 集群 双主 / DLedger

背景

RocketMQ 的部署和配置较为复杂,有众多配置项和部署方式可以选择。用户往往难以快速部署 RocketMQ,进行开发和验证。

rocketmq-dockeropen in new window 这个项目提供了 RocketMQ 的 docker 镜像打包实现,并且提供了常用的 docker-compose 模板,可以很快地用 Docker 启动 RocketMQ,并支持多种部署模式。

环境准备

需要安装完成 Docker,并且可以连接 Docker Hub。然后用 git 拉取 rocketmq-docker 仓库,并进入该仓库。

git clone https://github.com/apache/rocketmq-docker.git
cd rocketmq-docker

镜像准备

可以预先准备好 RocketMQ 的镜像。本地构建或者从 Docker Hub 拉取官方打包的镜像都可以

本地构建 RocketMQ docker 镜像

这一步不是必须要的,也可以从 Docker Hub 中拉取官方镜像。

本地构建的最大意义在于,如果自己修改了 RocketMQ 的源码,则可以用这种方式构建自己的镜像。

cd image-build
sh build-image.sh RMQ-VERSION BASE-IMAGE

运行脚本之后,会拉取相应版本的 RocketMQ 安装包到本地,然后构建镜像包。

其中 RMQ-VERSION 是需要构建的 RocketMQ 版本,在 这个地方open in new window 查看可选版本列表。

BASE-IMAGE 可以在 centosalpine 中选择。比如当前最新版本为 4.9.4,那么可以用如下命令打镜像

sh build-image.sh 4.9.4 alpine

打包完成后可以用如下命令查看

$ docker images
REPOSITORY                          TAG            IMAGE ID       CREATED         SIZE
apacherocketmq/rocketmq             4.9.4-alpine   58e1e7a5e556   16 hours ago    188MB

拉取远程

$ docker search rocketmq
NAME                                 DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
foxiswho/rocketmq                    rocketmq                                        77                   
rocketmqinc/rocketmq                 Image repository for Apache RocketMQ            54                   
styletang/rocketmq-console-ng        rocketmq-console-ng                             38                   
apache/rocketmq                                                                      25                   
apacherocketmq/rocketmq              Docker Image for Apache RocketMQ                22                   

我们选择 apache/rocketmq,其他的版本已经跟不上时代了,年久失修。

看一下它支持的版本号列表:

选择最新的 4.9.4 版本拉取

$ docker pull apache/rocketmq:4.9.4

Docker 启动 RocketMQ

首先需要用版本号来创建一个 stage 文件夹,运行如下命令

$ sh stage.sh 4.9.4

会在根目录下创建一个 stage 文件夹,进入到 stage/4.9.4/templates 目录下(有的 Linux 系统生成的路径是 stage/4.9.4/

$ cd stages/4.9.4/templates/
$ ls -l
drwxrwxr-x 6 ubuntu ubuntu 4096 Jul 24 15:25 ./
drwxrwxr-x 3 ubuntu ubuntu 4096 Jul 24 15:23 ../
drwxrwxr-x 6 ubuntu ubuntu 4096 Jul 24 15:23 data/
drwxrwxr-x 4 ubuntu ubuntu 4096 Jul 24 15:26 docker-compose/
drwxrwxr-x 2 ubuntu ubuntu 4096 Jul 24 15:23 kubernetes/
-rwxrwxr-x 1 ubuntu ubuntu  902 Jul 24 15:23 play-consumer.sh*
-rwxrwxr-x 1 ubuntu ubuntu 1497 Jul 24 15:23 play-docker-compose.sh*
-rwxrwxr-x 1 ubuntu ubuntu 3201 Jul 24 15:23 play-docker-dledger.sh*
-rwxrwxr-x 1 ubuntu ubuntu 2354 Jul 24 15:23 play-docker.sh*
-rwxrwxr-x 1 ubuntu ubuntu 2271 Jul 24 15:23 play-docker-tls.sh*
-rwxrwxr-x 1 ubuntu ubuntu  947 Jul 24 15:23 play-kubernetes.sh*
-rwxrwxr-x 1 ubuntu ubuntu  901 Jul 24 15:23 play-producer.sh*
drwxrwxr-x 2 ubuntu ubuntu 4096 Jul 24 15:23 ssl/

具体的原理是用原来 templates 下的模板,替换内容中的版本号,生成 4.9.4 版本的启动脚本。

其中的多个 .sh 文件是用来以不同部署方式启动 RocketMQ

用 docker-compose 以集群模式启动 RocketMQ

如果是采用远程拉取的镜像,首选需要修改一下 docker-compose.yml 文件保证使用的镜像名称正确。

最新的 rocketmq-docker 项目已经将 docker-compose.yml 中的镜像地址改为了官方镜像地址 apache/rocketmq,如果你拉取的版本没有改,需要进行修改。

此外,RocketMQ 有 brokerIP 配置,该配置默认会自动获取主机 IP,但是在容器中获取的是容器的 IP,客户端去连接会发现连不上。所以需要提前手动修改 Broker 配置的 IP。

$ pwd
/home/ubuntu/workspace/rocketmq/rocketmq-docker/stages/4.9.4/templates
$ vim docker-compose/data/broker/conf/broker.conf
$ vim docker-compose/data1/broker/conf/broker.conf

# broker.conf
brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH

# 改为宿主机的 IP
brokerIP1={宿主机IP}

改成宿主机 IP 之后,发现如果是用 2 个主节点,他们的监听 IP 都将会是 {宿主机IP}:10911,需要将 broker-b 映射的监听 port 修改一下。
修改 docker-compose.yml

  #Service for another broker -- broker1
  broker1:
    image: apache/rocketmq:4.9.4
    container_name: rmqbroker-b
    links:
      - namesrv
    ports:
      # 修改映射到宿主机的 port
            #- 10929:10909
            #- 10931:10911
            #- 10932:10912
      - 10929:10929
      - 10931:10931
      - 10932:10932
    environment:
      - NAMESRV_ADDR=namesrv:9876
    volumes:
      - ./data1/broker/logs:/home/rocketmq/logs
      - ./data1/broker/store:/home/rocketmq/store
      - ./data1/broker/conf/broker.conf:/opt/rocketmq-4.9.4/conf/broker.conf
    command: sh mqbroker -c /opt/rocketmq-4.9.4/conf/broker.conf

docker-compose.yml 文件映射端口改了之外,还要修改 Broker2 的监听端口

$ pwd
/home/ubuntu/workspace/rocketmq/rocketmq-docker/stages/4.9.4/templates
$ vim docker-compose/data1/broker/conf/broker.conf

# broker.conf
brokerClusterName = DefaultCluster
brokerName = broker-b
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH

# 改为宿主机的 IP
brokerIP1={宿主机IP}
# 修改监听端口
listenPort=10931
fastListenPort=10929
haListenPort=10932

然后可以启动 RocketMQ 容器

$ pwd
/home/ubuntu/workspace/rocketmq/rocketmq-docker/stages/4.9.4/templates
$ vim docker-compose/docker-compose.yml
# (如果拉取远程镜像)把其中默认的 image 从 apacherocketmq/rocketmq:4.9.4 改成最新的官方镜像地址 apache/rocketmq:4.9.4
$ ./play-docker-compose.sh 
[+] Running 4/4
 ⠿ Network docker-compose_default  Created                                                                                       
 ⠿ Container rmqnamesrv            Started                                                                                       
 ⠿ Container rmqbroker-b           Started                                                                                       
 ⠿ Container rmqbroker             Started                                         

运行之后会启动两个 broker 和一个 nameserver

$ docker ps
CONTAINER ID   IMAGE                                     COMMAND                  CREATED              STATUS              PORTS                                                                                                                                                   NAMES
722c5c14d3d0   apache/rocketmq:4.9.4                     "sh mqbroker -c /opt…"   About a minute ago   Up About a minute   0.0.0.0:10909->10909/tcp, :::10909->10909/tcp, 9876/tcp, 0.0.0.0:10911-10912->10911-10912/tcp, :::10911-10912->10911-10912/tcp                          rmqbroker
a7d0e64c5335   apache/rocketmq:4.9.4                     "sh mqbroker -c /opt…"   About a minute ago   Up About a minute   9876/tcp, 0.0.0.0:10929->10909/tcp, :::10929->10909/tcp, 0.0.0.0:10931->10911/tcp, :::10931->10911/tcp, 0.0.0.0:10932->10912/tcp, :::10932->10912/tcp   rmqbroker-b
a210d64eddb5   apache/rocketmq:4.9.4                     "sh mqnamesrv"           About a minute ago   Up About a minute   10909/tcp, 0.0.0.0:9876->9876/tcp, :::9876->9876/tcp, 10911-10912/tcp                                                                                   rmqnamesrv

使用 docker 启动 RocketMQ-dashboard

RocketMQ-dashboard 项目是 rocketmq 的控制台,可以可视化的查看 rocketmq 集群状态。也可以用 docker 启动。直接使用官方打包好的镜像,不本地构建了。

用 docker 单独启动 rocketmq-dashboard

需要先修改 start-dashboard.sh 文件

$ pwd
/home/ubuntu/workspace/rocketmq/rocketmq-docker
$ vim product/start-dashboard.sh

将镜像名称改成 apacherocketmq/rocketmq-dashboard

# 修改后
ROCKETMQ_DASHBOARD_VERSION=$1

docker run -d -it --name rocketmq-dashboard -p 6765:8080 apacherocketmq/rocketmq-dashboard:${ROCKETMQ_DASHBOARD_VERSION}

然后运行

$ sh start-dashboard.sh 1.0.0

会启动 rocketmq-dashboard 的 container

$ docker ps
CONTAINER ID   IMAGE                                     COMMAND                  CREATED          STATUS          PORTS                                                                                                                                                   NAMES
433021cbeb23   apacherocketmq/rocketmq-dashboard:1.0.0   "sh -c 'java $JAVA_O…"   45 minutes ago   Up 45 minutes   0.0.0.0:6765->8080/tcp, :::6765->8080/tcp                                                                                                               rocketmq-dashboard

这样启动之后,登录访问 host:6765 地址,设置集群的 nameserver 地址,但是与集群的网络不通。

与集群一起用 docker-compose 启动 docker-dashboard

还是要修改 docker-compose.yml 文件

$ cd stages/4.9.4/templates
$ vim docker-compose/docker-compose.yml

在文件尾部添加如下配置,启动一个 rocketmq-dashboard 服务,并置于和集群同一个网络下

  # Service for dashboard 
  dashboard: 
    image: apacherocketmq/rocketmq-dashboard:1.0.0 
    container_name: rmq-dashboard 
    ports: 
      - 48080:8080 
    environment: 
      - NAMESRV_ADDR=namesrv:9876 
    depends_on: 
      - namesrv 
    links: 
      - namesrv 

然后访问 host:48080 地址,可以通过 dashboard 查看集群状态

Docker 启动 DLedger 模式的 RocketMQ

用 DLedger 模式前保证有足够的可用内存(8G 以上)

也是有两种方法,用本地构建的镜像和 Docker Hub 中官方上传的镜像。如果用本地打包的镜像,直接运行如下命令

$ cd stages/4.9.4/templates
$ ./play-docker-dledger.sh

如果要用 Docker Hub 中的镜像,则需要修改 play-docker-dledger.sh 中的镜像地址

$ vim play-docker-dledger.sh
:%s/apacherocketmq/apache/g
$ ./play-docker-dledger.sh

但是我运行时三个 Broker 都未启动成功,查看 Broker 日志,发现 broker.conf 文件未找到

ubuntu@VM-4-14-ubuntu:~/workspace/rocketmq/rocketmq-docker/stages/4.9.4/templates$ docker ps
CONTAINER ID   IMAGE                   COMMAND                  CREATED         STATUS         PORTS                                                                                                                                NAMES
1ae8a853012b   apache/rocketmq:4.9.4   "sh mqbroker -c ../c…"   2 seconds ago   Up 1 second    9876/tcp, 10909/tcp, 0.0.0.0:30929->30929/tcp, :::30929->30929/tcp, 10911-10912/tcp, 0.0.0.0:30931->30931/tcp, :::30931->30931/tcp   rmqbroker2
71da5cd67513   apache/rocketmq:4.9.4   "sh mqnamesrv"           4 seconds ago   Up 3 seconds   10909/tcp, 0.0.0.0:9876->9876/tcp, :::9876->9876/tcp, 10911-10912/tcp                                                                rmqnamesrv
0e80d1d53112   redis:6.2               "docker-entrypoint.s…"   3 months ago    Up 3 months    0.0.0.0:46379->6379/tcp, :::46379->6379/tcp                                                                                          redis-redis-1
ubuntu@VM-4-14-ubuntu:~/workspace/rocketmq/rocketmq-docker/stages/4.9.4/templates$ docker ps -a
CONTAINER ID   IMAGE                                     COMMAND                  CREATED          STATUS                       PORTS                                                                   NAMES
1ae8a853012b   apache/rocketmq:4.9.4                     "sh mqbroker -c ../c…"   8 seconds ago    Exited (255) 6 seconds ago                                                                           rmqbroker2
b959cf8b6542   apache/rocketmq:4.9.4                     "sh mqbroker -c ../c…"   9 seconds ago    Exited (255) 6 seconds ago                                                                           rmqbroker1
919ce578e6db   apache/rocketmq:4.9.4                     "sh mqbroker -c ../c…"   10 seconds ago   Exited (255) 7 seconds ago                                                                           rmqbroker
71da5cd67513   apache/rocketmq:4.9.4                     "sh mqnamesrv"           10 seconds ago   Up 9 seconds                 10909/tcp, 0.0.0.0:9876->9876/tcp, :::9876->9876/tcp, 10911-10912/tcp   rmqnamesrv

ubuntu@VM-4-14-ubuntu:~/workspace/rocketmq/rocketmq-docker/stages/4.9.4/templates$ docker logs -t rmqbroker --tail=100
2022-07-27T15:58:11.218761998Z java.io.FileNotFoundException: ../conf/dledger/broker.conf (No such file or directory)
2022-07-27T15:58:11.218878131Z  at java.io.FileInputStream.open0(Native Method)
2022-07-27T15:58:11.218887204Z  at java.io.FileInputStream.open(FileInputStream.java:195)
2022-07-27T15:58:11.218891884Z  at java.io.FileInputStream.<init>(FileInputStream.java:138)
2022-07-27T15:58:11.218953791Z  at java.io.FileInputStream.<init>(FileInputStream.java:93)
2022-07-27T15:58:11.218960481Z  at org.apache.rocketmq.broker.BrokerStartup.createBrokerController(BrokerStartup.java:119)
2022-07-27T15:58:11.218965349Z  at org.apache.rocketmq.broker.BrokerStartup.main(BrokerStartup.java:57)

于是想办法修改 play-docker-dledger.sh 中的 Broker 配置文件路径,改成 /opt/rocketmq-4.9.4/conf/dledger/broker.conf,然后启动成功

修改内存配置

DLedger 模式默认配置下,每个节点会占用 2G 内存。如果是内存较小的机器则可以通过定义环境变量修改内存占用。

RocketMQ 使用 runbroker.sh 启动,其中启动参数设置脚本如下:

# runbroker.sh
JAVA_OPT="${JAVA_OPT} -server -Xms8g -Xmx8g"
choose_gc_options
JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow"
JAVA_OPT="${JAVA_OPT} -XX:+AlwaysPreTouch"
JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=15g"
JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages -XX:-UseBiasedLocking"
#JAVA_OPT="${JAVA_OPT} -Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n"
JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}"
JAVA_OPT="${JAVA_OPT} -cp ${CLASSPATH}"

这个脚本预留了定义额外的 Java 启动参数的环境变量,即 JAVA_OPT_EXT,于是将 play-docker-dledger.sh 文件做如下修改,添加 -e "JAVA_OPT_EXT=-server -Xms128m -Xmx128m -Xmn128m"(注意,这么小的内存无法生产消费消息,仅仅为了启动 Broker。需要同时改动 broker 配置中的 commitlog、consumequeue、indexfile 大小)

docker run --net dledger-br --ip 172.18.0.12 -d -p 30911:30911 -p 30909:30909 -v `pwd`/data/broker0/logs:/home/rocketmq/logs -v `pwd`/data/broker0/store:/home/rocketmq/store -v `pwd`/data/broker0/conf/dledger:/opt/rocketmq-4.9.4/conf/dledger --name rmqbroker --link rmqnamesrv:namesrv -e "NAMESRV_ADDR=namesrv:9876" -e "JAVA_OPT_EXT=-server -Xms128m -Xmx128m -Xmn128m" apache/rocketmq:4.9.4 sh mqbroker -c /opt/rocketmq-4.9.4/conf/dledger/broker.conf
docker run --net dledger-br --ip 172.18.0.13 -d -p 30921:30921 -p 30919:30919 -v `pwd`/data/broker1/logs:/home/rocketmq/logs -v `pwd`/data/broker1/store:/home/rocketmq/store -v `pwd`/data/broker1/conf/dledger:/opt/rocketmq-4.9.4/conf/dledger --name rmqbroker1 --link rmqnamesrv:namesrv -e "NAMESRV_ADDR=namesrv:9876" -e "JAVA_OPT_EXT=-server -Xms128m -Xmx128m -Xmn128m" apache/rocketmq:4.9.4 sh mqbroker -c /opt/rocketmq-4.9.4/conf/dledger/broker.conf
docker run --net dledger-br --ip 172.18.0.14 -d -p 30931:30931 -p 30929:30929 -v `pwd`/data/broker2/logs:/home/rocketmq/logs -v `pwd`/data/broker2/store:/home/rocketmq/store -v `pwd`/data/broker2/conf/dledger:/opt/rocketmq-4.9.4/conf/dledger --name rmqbroker2 --link rmqnamesrv:namesrv -e "NAMESRV_ADDR=namesrv:9876" -e "JAVA_OPT_EXT=-server -Xms128m -Xmx128m -Xmn128m" apache/rocketmq:4.9.4 sh mqbroker -c /opt/rocketmq-4.9.4/conf/dledger/broker.conf

DLedger 与 Dashboard 同时启动

需要修改 play-docker-dleger.sh,在 broker 运行的脚本下面添加 dashboard 的 docker 运行脚本,并与 broker、nameserver 用同一个网络

# Start brokers
# ...
# Start dashboard
docker run --net dledger-br -d -p 48080:8080 --link rmqnamesrv:namesrv -e "NAMESRV_ADDR=namesrv:9876" --name rmq-dledger-dashboard apacherocketmq/rocketmq-dashboard:1.0.0

然后运行 ./play-docker-dledger.sh,可以访问 48080 端口进入 Dashboard

以其他部署形式启动 RocketMQ

Docker 启动单节点 RocketMQ

$ cd stages/4.9.4/templates
$ sh play-docker.sh alpine

Docker 启动带 TLS 的 RocketMQ

$ cd stages/4.9.4/templates
$ sh play-docker-tls.sh

欢迎关注公众号【消息中间件】(middleware-mq),更新消息中间件的源码解析和最新动态!