0%

rocketmq集群搭建

之前自己使用rocketmq时写过一篇笔记,近期需要搭建一个rocketmq集群,发现rocketmq项目已经从apache毕业正式成为顶级项目,这里对笔记内容进行了更新,使用的版本和部署方式也按照rocketmq 4.9.4版本重新进行了整理

rocketmq集群角色

rocketmq架构与kafka非常相似:rocketmq集群角色分为namesrv和broker,namesrv负责broker的注册和管理、消息向broker上队列的投递/消费的路由,是管理节点。broker负责消息的存储、投递、查询,相当于工作节点,向指定的所有namesrv分别注册自身及管理的队列信息;每组broker可分为master和slave,写操作只可在master进行,读操作可以在任意节点进行。

producer向namesrv查询队列所在的broker,向这一组broker的master节点写入;consumer向namesrv查询队列所在的broker,向这一组broker的master或slave读取消息。不同组broker之间是数据分片的形式,每组broker持有一部分数据,因此可以通过扩容broker扩展消息存储量和读写性能。

高可用方案

多个namesrv之间互相不同步数据,而是每个namesrv节点都可以提供完整服务,因此可以直接集群部署、向外部提供namesrv列表来保证HA。

而broker则是主从模式,有以下几种集群方案:

  • 部署多组broker,每组broker只部署一个master节点。这样每个broker都是单点,一旦master宕机则这组broker涉及到的队列、消息不可用,直到节点恢复
  • 部署多组broker,每组broker部署master和slave节点,主从之间异步写入进行数据复制。这样每组broker具备主从备份,单个节点宕机仍可从其他节点读取,不过因为是异步写入,主从同步延迟会导致数据不一致
  • 部署多组broker,每组broker部署master和slave节点,主从同步写入进行数据复制。相比第二种方式可以避免异步写入情况下master宕机带来的数据不一致,但是写入延迟必然增加——此所谓CAP不可得兼也

在集群中,不同组的broker通过broker-name区分,同一组broker的不同节点通过broker-id区分,且约定master的broker-id为0

因为master/salve节点只是broker-id不同,配置和启动方式没有区别,因此这里只演示第一种模式——多组broker、每组broker只包含master节点的集群搭建。

部署情况

需要部署:

  • rocketmq-namesrv,是broker的注册中心
  • broker,消息的收发处理
  • dashbroad,管理页面

防火墙需要开放以下端口:

  • namesrv监听端口,默认为9876
  • broker监听端口,用于broker与namesrv/client的通信,默认为:10911,10912, 10909
  • dashboard监听端口,默认为8080

部署路径为:

1
/home/rocketmq/rocketmq-4.9.4

安装java

此处不述,有需要可参考java快速部署工具

部署namesrv

创建namesrv配置文件,

1
2
cd /home/rocketmq/rocketmq-4.9.4/conf/
touch namesrv.properties

编辑配置文件,视需求增加/修改配置,如:

1
2
3
4
# namesrv监听端口
listenPort=9876
# 是否启用顺序消息
orderMessageEnable=true

修改bin/runserver.sh,视情况调整namesrv堆内存和堆外内存等的大小:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 视情况调整namesrv堆内存和堆外内存等的大小
choose_gc_options()
{
# Example of JAVA_MAJOR_VERSION value : '1', '9', '10', '11', ...
# '1' means releases befor Java 9
JAVA_MAJOR_VERSION=$("$JAVA" -version 2>&1 | sed -r -n 's/.* version "([0-9]*).*$/\1/p')
if [ -z "$JAVA_MAJOR_VERSION" ] || [ "$JAVA_MAJOR_VERSION" -lt "9" ] ; then
JAVA_OPT="${JAVA_OPT} -server -Xms4g -Xmx4g -Xmn2g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
JAVA_OPT="${JAVA_OPT} -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSClassUnloadingEnabled -XX:SurvivorRatio=8 -XX:-UseParNewGC"
JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:${GC_LOG_DIR}/rmq_srv_gc_%p_%t.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps"
JAVA_OPT="${JAVA_OPT} -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m"
else
JAVA_OPT="${JAVA_OPT} -server -Xms4g -Xmx4g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0"
JAVA_OPT="${JAVA_OPT} -Xlog:gc*:file=${GC_LOG_DIR}/rmq_srv_gc_%p_%t.log:time,tags:filecount=5,filesize=30M"
fi
}

启动namesrv,启动时需要使用-c指定配置文件

1
cd /home/rocketmq/rocketmq-4.9.4/bin &&  nohup sh mqnamesrv  -c ../conf/namesrv.properties > /dev/null 2>&1 &

默认日志输出到${user.home}/logs下,即启动进程的用户目录下logs内,需要修改则改动conf/logback_namesrv.xml

部署broker

broker可集群化部署,多组broker之间使用brokerName区分

1
cd /home/rocketmq/rocketmq-4.9.4/conf

修改broker.conf文件,关键配置如下:

1
2
3
4
5
6
7
8
9
10
# cluster名
brokerClusterName = DefaultCluster
# broker名称,多组broker之间使用brokerName区分
brokerName = broker-a
# 一组broker内,id为0的为master,其他为slave
brokerId = 0
# 指定namesrv地址,多个地址则使用';'分割
namesrvAddr=localhost:9876
# 启用acl
aclEnable=true

如果需要指定broker注册的IP,可以在配置文件中使用brokerIP1指定

1
2
3
# 指定broker注册的IP
# 如果需要外网客户端连接,可指定为公网地址,比如:
brokerIP1 = 192.168.226.138

broker默认JVM配置中内存Xms为8G,可以视情况调整:

1
cd /home/rocketmq/rocketmq-4.9.4/bin

修改runbroker.sh:

1
2
3
# 视情况调整broker堆内存和堆外内存大小
JAVA_OPT="${JAVA_OPT} -server -Xms8g -Xmx8g"
JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=15g"

启动broker:

1
cd /home/rocketmq/rocketmq-4.9.4/bin &&  nohup sh mqbroker -c ../conf/broker.conf  &

对于broker主从,区别只是brokerId,master节点的brokerId约定为0,其他slave按情况分配;对于多组broker的情况,多组broker只需要修改brokerName进行区分

acl配置

rocketmq支持acl配置多用户角色、权限,以控制对broker的访问、操作权限

1
2
3
4
5
# conf下创建acl目录,broker启动时默认读取此目录下配置文件
mkdir /home/rocketmq/rocketmq-4.9.4/conf/acl
cd /home/rocketmq/rocketmq-4.9.4/conf/acl
# conf目录下有plain_acl.yml示例
cp /home/rocketmq/rocketmq-4.9.4/conf/plain_acl.yml .

在plain_acl.yml可管理用户账号及权限

同时需要修改broker.conf,开启acl:

1
2
# 开启acl
aclEnable=true

重启broker进程后生效

部署rocketmq-dashbroad

为了方便直接使用docker部署rocketmq-dashbroad

1
2
3
docker pull apacherocketmq/rocketmq-dashboard:latest

docker run -d --name rocketmq-dashboard -e "JAVA_OPTS=-Drocketmq.namesrv.addr=192.168.226.138:9876 -Drocketmq.config.accessKey=rocketmq -Drocketmq.config.secretKey=rocketmq.123" -p 8080:8080 -t apacherocketmq/rocketmq-dashboard:latest

其中,rocketmq.namesrv.addr指定namesrv地址(多个地址则使用’;’分割),需要注意的是:

  1. 使用docker默认网络模式情况下,容器具有单独网络空间,地址不能使用localhost/127.0.0.1,需要指定为namesrv所在的内网/外网地址
  2. 因为rocketmq开启了acl,dashbroad需要指定rocketmq.config.accessKey、rocketmq.config.secretKey
  3. dashbroad默认监听8080端口,这里映射到了主机8080端口