title: Activemq集群部署 #标题tags: mq #标签
date: 2020-08-12
categories: MQ # 分类
Activemq默认使用kahaDB持久化方式,但在5.9以上ActiveMQ版本,可利用zookeeper+levelDB的方法,此方法利用zookerper控制broker的主从,每个节点有自己的一个levelDB模式的存储文件,3节点activemq集群的情况下每次发送和消费只有当2个activemq都完成更新的时候才算成功,当master节点挂掉的时候会控制最新更新的一个broker节点成为新的master。
此文章部署的activemq版本为5.16.0。
补充1:在我浏览levedb相关文档时,发现官方文档中有如下提示(我想静静):
补充2:注意事项
LevelDB存储尚不支持存储与Delay和Schedule Message Delivery相关的数据。这些存储在单独的非复制KahaDB数据文件中。如果将“延迟”和“计划消息传递”与复制的leveldb存储一起使用,则会发生意外结果,因为当主服务器故障转移到从服务器时,该数据将不存在。
Activemq集群部署方案比较
摘自:ActiveMq 集群部署 三种方案 + 负载均衡+其他细节点
存储及性能比较
默认的单机部署(kahadb)
activeMQ的默认存储的单机方式,以本地kahadb文件的方式存储,所以性能指标完全依赖本地磁盘IO,不能提供高可用。
基于zookeeper的主从(levelDB Master/Slave)
5.9.0新推出的主从实现,基于zookeeper来选举出一个master,其他节点自动作为slave实时同步消息。
因为有实时同步数据的slave的存在,master不用担心数据丢失,所以leveldb会优先采用内存存储消息,异步同步到磁盘。所以该方式的activeMQ读写性能都最好,特别是写性能能够媲美非持久化消息。
优点:
1、实现高可用和数据安全。
2、性能较好。
缺点:
1、 因为选举机制要超过半数,所以最少需要3台节点,才能实现高可用。
基于共享数据库的主从(Shared JDBC Master/Slave)
可以基于postgres、mysql、oracle等常用数据库。
每个节点启动都会争抢数据库锁,从而保证master的唯一性,其他节点作为备份,一直等待数据库锁的释放。
因为所有消息读写,其实都是数据库操作,activeMQ节点本身压力很小,性能完全取决于数据库性能。
优点:
1、实现高可用和数据安全
2、简单灵活,2台节点就可以实现高可用
缺点:
1、稳定性依赖数据库
2、性能依赖数据库
灾备方案比较
leveldb方式
需要3台节点,2台在主机房,1台在备机房,主机房的节点权重设的比备机房节点高。
当master节点故障:
因为权重的关系,主机房另一个节点会自动被选举为新的master。
当主机房故障:
需要启动备用机房时,先更改备机房节点配置,把集群规模从3改成1,这样1个节点可以临时提供服务(此时不再保证高可用)。
共享数据库方式
3台节点即可,2台在主机房,1台在备机房,备机房节点指向灾备activeMQ数据库,平时要关闭。
当master节点故障:
主机房的另一个节点会自动取得数据库锁,成为新的master。
当主机房故障:
需要启动备用机房时,先完成activeMQ数据库的切换,然后启动灾备activeMQ节点即可临时外提供服务(此时不再保证高可用)。
好了,废话不多说,开始部署
环境准备
OS | hostname | IP | service | Port |
---|---|---|---|---|
Centos 7.5 | amq1 | 192.168.20.2 | zookeeper、activemq | 62621(集群端口)、61616(消息端口)、8161(管控台端口) |
Centos 7.5 | amq2 | 192.168.20.3 | zookeeper、activemq | 62621(集群端口)、61616(消息端口)、8161(管控台端口) |
Centos 7.5 | amq3 | 192.168.20.4 | zookeeper、activemq | 62621(集群端口)、61616(消息端口)、8161(管控台端口) |
部署zookeeper集群
配置java环境
所有机器都需配置。
自行去oracle官网下载java包,然后上传至各个服务器。
# 配置jdk环境(jdk版本不可过高,已验证jdk 14会在activemq启动后无法连接到zookeeper)
$ tar zxf jdk-8u261-linux-x64.tar.gz -C /opt/
$ ln -sf /opt/jdk1.8.0_261 /opt/jdk
$ cat >> /etc/profile << EOF
export JAVA_HOME=/opt/jdk
export CLASSPATH=\$JAVA_HOME/lib
export PATH=\$JAVA_HOME/bin:\$PATH
EOF
$ source /etc/profile
$ $ java -version # 查看版本信息
java version "1.8.0_261"
Java(TM) SE Runtime Environment (build 1.8.0_261-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.261-b12, mixed mode)
部署zookeeper
以下操作在amq1配置即可。
# 下载
cd /opt/
wget https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.6.2/apache-zookeeper-3.6.2-bin.tar.gz
tar zxf apache-zookeeper-3.6.2-bin.tar.gz
ln -sf /opt/apache-zookeeper-3.6.2-bin /opt/zk
# 配置
cd /opt/zk/conf/
mkdir /opt/zk/data
echo 1 > /opt/zk/data/myid
$ cat /opt/zk/conf/zoo.cfg # 编写配置文件如下
dataDir=/opt/zk/data
clientPort=2181
maxClientCnxns=0
tickTime=2000
initLimit=10
syncLimit=5
quorumListenOnAllIPs=true
server.1=192.168.20.2:2888:3888
server.2=192.168.20.3:2888:3888
server.3=192.168.20.4:2888:3888
# 将zookeeper目录发送至其他节点
$ for i in `seq 3 4`;do rsync -az /opt/apache-zookeeper-3.6.2-bin 192.168.20.${i}:/opt/;done
# 启动192.168.20.2节点的zookeeper
$ /opt/zk/bin/zkServer.sh --config /opt/zk/conf start
# 只有leader才会监听28888
ss -lnpt | egrep '2181|3888|2888'
修改amq2节点的配置文件
ln -sf /opt/apache-zookeeper-3.6.2-bin/ /opt/zk
echo 2 > /opt/zk/data/myid
修改amq3节点的配置文件
ln -sf /opt/apache-zookeeper-3.6.2-bin/ /opt/zk
echo 3 > /opt/zk/data/myid
执行以下指令启动各个zookeeper节点
/opt/zk/bin/zkServer.sh --config /opt/zk/conf start
ss -lnpt | egrep '2181|3888|2888' # 确定端口在监听
# 别忘了,只有leader才会监听2888
验证zookeeper集群状态
如何查看Zookeeper中的数据呢,我们可以通过ZkCli.sh命令客户端查看,但是不太直观,因为ZK本身数据是以树型结构存储组织的,所以这里推荐一个实用的界面操作工具——ZooInspector。
1、下载 https://issues.apache.org/jira/secure/attachment/12436620/ZooInspector.zip;
2、运行zookeeper-dev-ZooInspector.jar
- 解压,进入目录ZooInspector\build。
- 在build目录,按住shift键右键鼠标,在右键菜单出选择“在此处打开powershell窗口”。
- 执行命令
java -jar .\zookeeper-dev-ZooInspector.jar
执行成功后,会弹出java ui client。如下:
点击上面箭头所示,然后输入zookeeper连接信息,如下:
既可看到集群相关信息,如下:
至此,zookeeper集群部署完成。
部署activemq集群
部署amq1
接下来的操作只需要在amq1这台机器执行。
# 下载及解压
$ wget https://mirrors.tuna.tsinghua.edu.cn/apache/activemq/5.16.0/apache-activemq-5.16.0-bin.tar.gz
$ tar zxf apache-activemq-5.16.0-bin.tar.gz -C /opt/
$ ln -sf /opt/apache-activemq-5.16.0 /opt/activemq
$ cd /opt/activemq/
########### 配置与优化 ###########
# 修改active启动内存
$ vim /opt/activemq/bin/env
ACTIVEMQ_OPTS_MEMORY="-Xms64M -Xmx1G" # 找到此行
# 改为如下,建议Xms和Xmx值为一致,并且是系统内存的一半
ACTIVEMQ_OPTS_MEMORY="-Xms2G -Xmx2G"
# 修改配置文件
$ vim /opt/activemq/conf/activemq.xml
# 找到(40行左右)
# 注意:每个activemq的BrokerName必须相同,否则不能加入集群。
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}">
# 改为
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="activemq-cluster" dataDirectory="${activemq.data}" schedulerSupport="true">
# useJmx="true" :网上有些文档增加了此参数,其实没必要,useJmx默认为true。
# 找到82行左右,如下:
<persistenceAdapter>
<kahaDB directory="${activemq.data}/kahadb"/>
</persistenceAdapter>
改为:
<persistenceAdapter>
<!-- <kahaDB directory="${activemq.data}/kahadb"/> -->
<replicatedLevelDB
directory="${activemq.data}/leveldb"
replicas="3"
bind="tcp://0.0.0.0:62621"
zkAddress="192.168.20.2:2181,192.168.20.3:2181,192.168.20.4:2181"
hostname="192.168.20.2" zkPath="/activemq/leveldb-stores"/>
# hostname建议写为你机器的IP
</persistenceAdapter>
# zkAddress:为你zookeeper集群所有节点地址。
# hostname:自定义即可,但参与集群的hostname不可冲突,建议配置为本机IP。
# zkPath:自定义zookeeper中的存储路径。
# 找到(91行左右),以下是定义存储文件最大限制,一般可能需要更改storeUsage中的值
# tempUsaage是调整非持久文件限制
# memoryUsage是调整内存使用限制,默认是java虚拟机可用内存的70%
<systemUsage>
<systemUsage>
<memoryUsage>
<memoryUsage percentOfJvmHeap="70" />
</memoryUsage>
<storeUsage>
<storeUsage limit="100 gb"/>
</storeUsage>
<tempUsage>
<tempUsage limit="50 gb"/>
</tempUsage>
</systemUsage>
</systemUsage>
# 找到(大概118行左右)
<transportConnectors>
<!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
# 从这里开始注释 <!--
<transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
--> # 注释到这里结束
</transportConnectors>
# 修改WEB管理页面监听地址及端口
$ vim /opt/activemq/conf/jetty.xml
<bean id="jettyPort" class="org.apache.activemq.web.WebConsolePort" init-method="start">
<!-- the default port number for the web console -->
<property name="host" value="0.0.0.0"/> # 监听地址
<property name="port" value="8161"/> # 监听端口
</bean>
$ vim /opt/activemq/conf/jetty-realm.properties # 修改管理台用户密码
admin: 123.com, admin
# 注意:用户名和密码的格式是 用户名:密码:角色名。
# 将修改好的activemq目录发送至其他节点
$ cd /opt/
$ for i in `seq 3 4`;do rsync -az apache-activemq-5.16.0 192.168.20.$i:/opt/;done
配置amq2
$ ln -sf /opt/apache-activemq-5.16.0 /opt/activemq
$ vim /opt/activemq/conf/activemq.xml
# 找到89行,修改如下
<persistenceAdapter>
<!-- <kahaDB directory="${activemq.data}/kahadb"/> -->
<replicatedLevelDB
directory="${activemq.data}/leveldb"
replicas="3"
bind="tcp://0.0.0.0:62621"
zkAddress="192.168.20.2:2181,192.168.20.3:2181,192.168.20.4:2181"
hostname="192.168.20.3" zkPath="/activemq/leveldb-stores"/>
# hostname建议写为你机器的IP
</persistenceAdapter>
# 可以通过zookeeper连接选项中的 weight 选项,控制master的选举
# 具体可以参考官方文档:http://activemq.apache.org/replicated-leveldb-store.html
配置amq3
$ ln -sf /opt/apache-activemq-5.16.0 /opt/activemq
$ vim /opt/activemq/conf/activemq.xml
# 找到89行,修改如下
<persistenceAdapter>
<!-- <kahaDB directory="${activemq.data}/kahadb"/> -->
<replicatedLevelDB
directory="${activemq.data}/leveldb"
replicas="3"
bind="tcp://0.0.0.0:62621"
zkAddress="192.168.20.2:2181,192.168.20.3:2181,192.168.20.4:2181"
hostname="192.168.20.4" zkPath="/activemq/leveldb-stores"/>
# hostname建议写为你机器的IP
</persistenceAdapter>
启动各个amq节点
$ /opt/activemq/bin/activemq start # 每台机器执行此指令,启动amq
# 如果启动失败,请查看日志
$ tailf -200 /opt/activemq/data/activemq.log
检查activemq运行情况
$ /opt/activemq/bin/activemq status # 查看amq的运行状态,其中会输出其pid号
$ ss -lnptu | grep 34358 # 一般master节点会监听如下端口(其中有一个是随机的)
# 我grep过滤的是activema的pid号
tcp LISTEN 0 50 [::]:38347 [::]:* users:(("java",pid=34358,fd=14))
tcp LISTEN 0 128 [::]:61616 [::]:* users:(("java",pid=34358,fd=147))
tcp LISTEN 0 100 [::]:62621 [::]:* users:(("java",pid=34358,fd=143))
tcp LISTEN 0 50 [::]:8161 [::]:* users:(("java",pid=34358,fd=150))
$ ss -lnptu | grep 34933 # salve节点只会监听一个随机端口
tcp LISTEN 0 50 [::]:34003 [::]:* users:(("java",pid=34933,fd=14))
集群节点分析
查看zookeeper信息
运行zookeeper工具进行监控,随机连接至一台zookeeper,如下:
连接后下图可以看到ActiveMQ有3个节点,其中0000000000节点的elected值不为空且address路径也不为空,可以确定为是master,这里3台的文件路径为之前设置的zkPath:
查看web管理台信息
在三台amq机器中,我们只能访问当前master的web控制台,salve是不会监听web控制台的,当master宕机后,slave选举出的master将继续监听web控制台端口,如下(admin/123.com 为我们在amq配置文件中自定义的):
能看到如上信息,就可以将amq的连接信息给开发小伙伴使用了。