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 << EOFexport JAVA_HOME=/opt/jdkexport CLASSPATH=\$JAVA_HOME/libexport PATH=\$JAVA_HOME/bin:\$PATHEOF$ 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.gztar zxf apache-zookeeper-3.6.2-bin.tar.gzln -sf /opt/apache-zookeeper-3.6.2-bin /opt/zk# 配置cd /opt/zk/conf/mkdir /opt/zk/dataecho 1 > /opt/zk/data/myid$ cat /opt/zk/conf/zoo.cfg # 编写配置文件如下dataDir=/opt/zk/dataclientPort=2181maxClientCnxns=0tickTime=2000initLimit=10syncLimit=5quorumListenOnAllIPs=trueserver.1=192.168.20.2:2888:3888server.2=192.168.20.3:2888:3888server.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才会监听28888ss -lnpt | egrep '2181|3888|2888'
修改amq2节点的配置文件
ln -sf /opt/apache-zookeeper-3.6.2-bin/ /opt/zkecho 2 > /opt/zk/data/myid
修改amq3节点的配置文件
ln -sf /opt/apache-zookeeper-3.6.2-bin/ /opt/zkecho 3 > /opt/zk/data/myid
执行以下指令启动各个zookeeper节点
/opt/zk/bin/zkServer.sh --config /opt/zk/conf startss -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/envACTIVEMQ_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"/> --><replicatedLevelDBdirectory="${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"/> --><replicatedLevelDBdirectory="${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"/> --><replicatedLevelDBdirectory="${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的连接信息给开发小伙伴使用了。
