概述
- 基于zookeeper和LevelDB搭建ActiveMQ集群。
- 集群仅提供主备方式的高可用集群功能,避免单点故障。
集群实现方案
- 基于shareFileSystem共享文件系统(KahaDB)
- 基于JDBC
- 基于可复制的LevelDB
LevelDB,5.6版本之后推出了LecelDB的持久化引擎,它使用了自定义的索引代替常用的BTree索引,其持久化性能高于KahaDB,虽然默认的持久化方式还是KahaDB,但是LevelDB可能会是趋势。
在5.9版本还提供了基于LevelDB和Zookeeper的数据复制方式,作为Master-Slave方式的首选数据复制方案。
zookeeper+replicated-leveldb-store的主从集群
概述
- 从ActiveMQ5.9开始,ActiveMQ的集群实现方式取消了传统的Masster-Slave方式.,增加了基于Zookeeper+LevelDB的Master-Slave实现方式,从5.9版本后也是官网的推荐。
- 基于Zookeeper和LevelDB搭建ActiveMQ集群,集群仅提供主备方式的高可用集群功能,避免单点故障
官方集群原理
- 上图意思是当Master宕机后,zookeper 监测到没有心跳信号, 则认为 master 宕机了,然后选举机制会从剩下的 Slave 中选出一个作为 新的 Master 。
- 使用Zookeeper集群注册所有的ActiveMQ Broker但只有其中一个Broker可以提供服务,它将被视为Master,其他的Broker处于待机状态被视为Slave。
- 如果Master因故障而不能提供服务,Zookeeper会从Slave中选举出一个Broker充当Master。Slave连接Master并同步他们的存储状态,Slave不接受客户端连接。所有的存储操作都将被复制到连接至Maste的Slaves。
- 如果Master宕机得到了最新更新的Slave会变成Master。故障节点在恢复后会重新加入到集群中并连接Master进入Slave模式。
- 所有需要同步的消息操作都将等待存储状态被复制到其他法定节点的操作完成才能完成。
所以,如给你配置了replicas=3,仲裁大小是(3/2)+1 = 2。Master将会存储更新然后等待(2-1)=1个Slave存储和更新完成,才汇报success。 - 当一个新的Master被选中,你需要至少保障一个法定node在线以能够找到拥有最新状态的node,这个node才可以成为新的Master。
- 因此,推荐运行至少3个replica nodes以防止一个node失败后服务中断。
构建过程
1、集群节点规划
节点编号 | 主机IP | ZK集群端口 | ZK安装目录 | AMQ集群bind端口 | AMQ消息tcp端口 | AMQ管理控制台端口 | AMQ安装目录 |
---|---|---|---|---|---|---|---|
ActiveMQ01 | 192.168.67.140 | 2181 | /myZookeeper3.4.14/zookeeper-3.4.14 | bind=“tcp://0.0.0.0:63631” | 61616 | 8161 | /myactivemq/apache-activemq-5.16.0 |
ActiveMQ02 | 192.168.67.180 | 2181 | /myZookeeper3.4.14/zookeeper-3.4.14 | bind=“tcp://0.0.0.0:63632” | 61616 | 8162 | /myactivemq/apache-activemq-5.16.0 |
ActiveMQ03 | 192.168.67.190 | 2181 | /myZookeeper3.4.14/zookeeper-3.4.14 | bind=“tcp://0.0.0.0:63633” | 61616 | 8163 | /myactivemq/apache-activemq-5.16.0 |
2、ZooKeeper集群
ZooKeeper集群的构建过程,参见CentOS下安装ZooKeeper中的分布式安装部署小节
3、ActiveMQ集群
(1)下载并解压ActiveMQ(三台服务器相同)
tar -zxvf apache-activemq-5.16.0-bin.tar.gz
(2)修改管理控制台端口
ActiveMQ01节点配置
ActiveMQ02节点配置
ActiveMQ03节点配置
(3)三个节点的brokerName一致(在activemq.xml配置文件中)
(4)持久化配置
ActiveMQ01配置
ActiveMQ02配置
ActiveMQ03配置
(5)启动ActiveMQ集群
前提条件:先启动ZooKeeper集群
分别启动三个ActiveMQ服务
[root@CentOS001 bin]# ./activemq start
[root@CentOS004 bin]# ./activemq start
[root@CentOS005 bin]# ./activemq start
(6)登录ZooKeeper查看ActiveMQ集群状态
[zk: localhost:2181(CONNECTED) 0] ls /
[activemq, zookeeper, sanguo, atguigu, f, demo, zk-test0000000002, lock-space123, 2010dd, mycat, servers, tttt, htzw]
[zk: localhost:2181(CONNECTED) 1]
[zk: localhost:2181(CONNECTED) 1] ls /activemq
[leveldb-stores]
[zk: localhost:2181(CONNECTED) 2] ls /activemq/leveldb-stores
[00000000003, 00000000004, 00000000005]
[zk: localhost:2181(CONNECTED) 3] get /activemq/leveldb-stores/0000000000
00000000003 00000000004 00000000005
[zk: localhost:2181(CONNECTED) 3] get /activemq/leveldb-stores/00000000000
Node does not exist: /activemq/leveldb-stores/00000000000
[zk: localhost:2181(CONNECTED) 4] get /activemq/leveldb-stores/0000000000
00000000003 00000000004 00000000005
[zk: localhost:2181(CONNECTED) 4] get /activemq/leveldb-stores/00000000003
{"id":"activemq","container":null,"address":"tcp://192.168.67.180:63632","position":-1,"weight":1,"elected":"0000000003"}
cZxid = 0x1a0000001f
ctime = Thu Nov 05 16:16:39 CST 2020
mZxid = 0x1a00000027
mtime = Thu Nov 05 16:16:40 CST 2020
pZxid = 0x1a0000001f
cversion = 0
dataVersion = 4
aclVersion = 0
ephemeralOwner = 0x10003a6ef960000
dataLength = 121
numChildren = 0
[zk: localhost:2181(CONNECTED) 5] get /activemq/leveldb-stores/00000000004
{"id":"activemq","container":null,"address":null,"position":-1,"weight":1,"elected":null}
cZxid = 0x1a00000022
ctime = Thu Nov 05 16:16:40 CST 2020
mZxid = 0x1a00000025
mtime = Thu Nov 05 16:16:40 CST 2020
pZxid = 0x1a00000022
cversion = 0
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x2001268fd220005
dataLength = 89
numChildren = 0
[zk: localhost:2181(CONNECTED) 6] get /activemq/leveldb-stores/00000000005
{"id":"activemq","container":null,"address":null,"position":-1,"weight":1,"elected":null}
cZxid = 0x1a0000002a
ctime = Thu Nov 05 16:16:41 CST 2020
mZxid = 0x1a0000002a
mtime = Thu Nov 05 16:16:41 CST 2020
pZxid = 0x1a0000002a
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x10003a6ef960001
dataLength = 89
numChildren = 0
[zk: localhost:2181(CONNECTED) 7]
(7)管理界面访问
此时只能访问master的管理界面,slave节点不能提供访问
以下两个Slave节点的管理界面无法访问
集群可用性测试
- ActiveMQ的客户端只能访问Master的Broker,其他处于Slave的Broker不能访问,所以客户端连接的Broker应该使用failover协议(失败转移)
- 当一个ActiveMQ节点挂掉或者一个Zookeeper节点挂点,ActiveMQ服务依然正常运转,如果仅剩一个ActiveMQ节点,由于不能选举Master,所以ActiveMQ不能正常运行。
- 同样的,如果zookeeper仅剩一个活动节点,不管ActiveMQ各节点存活,ActiveMQ也不能正常提供服务。
- ActiveMQ集群的高可用依赖于Zookeeper集群的高可用
- 集群需要使用
(failover:(tcp://192.168.67.130:61616,tcp://192.168.67.180:61616,tcp://192.168.67.190:61616))
配置多个ActiveMQ
ActiveMQ测试故障切换
关闭Master节点,并从ZK中查看选举状态
[root@CentOS001 bin]# ./activemq stop
INFO: Loading '/myactivemq/apache-activemq-5.16.0//bin/env'
INFO: Using java '/usr/java/jdk1.8.0_161/bin/java'
INFO: Waiting at least 30 seconds for regular process termination of pid '13776' :
Java Runtime: Oracle Corporation 1.8.0_161 /usr/java/jdk1.8.0_161/jre
Heap sizes: current=62976k free=61992k max=932352k
JVM args: -Xms64M -Xmx1G -Djava.util.logging.config.file=logging.properties -Djava.security.auth.login.config=/myactivemq/apache-activemq-5.16.0//conf/login.config -Dactivemq.classpath=/myactivemq/apache-activemq-5.16.0//conf:/myactivemq/apache-activemq-5.16.0//../lib/: -Dactivemq.home=/myactivemq/apache-activemq-5.16.0/ -Dactivemq.base=/myactivemq/apache-activemq-5.16.0/ -Dactivemq.conf=/myactivemq/apache-activemq-5.16.0//conf -Dactivemq.data=/myactivemq/apache-activemq-5.16.0//data
Extensions classpath:
[/myactivemq/apache-activemq-5.16.0/lib,/myactivemq/apache-activemq-5.16.0/lib/camel,/myactivemq/apache-activemq-5.16.0/lib/optional,/myactivemq/apache-activemq-5.16.0/lib/web,/myactivemq/apache-activemq-5.16.0/lib/extra]
ACTIVEMQ_HOME: /myactivemq/apache-activemq-5.16.0
ACTIVEMQ_BASE: /myactivemq/apache-activemq-5.16.0
ACTIVEMQ_CONF: /myactivemq/apache-activemq-5.16.0/conf
ACTIVEMQ_DATA: /myactivemq/apache-activemq-5.16.0/data
Connecting to pid: 13776
.Stopping broker: activemq
. TERMINATED
[root@CentOS001 bin]#
[zk: localhost:2181(CONNECTED) 0] zkCli.sh
[zk: localhost:2181(CONNECTED) 0] ls /
[activemq, zookeeper, sanguo, atguigu, f, demo, zk-test0000000002, lock-space123, 2010dd, mycat, servers, tttt, htzw]
[zk: localhost:2181(CONNECTED) 1] ls /activemq
[leveldb-stores]
[zk: localhost:2181(CONNECTED) 2] ls /activemq/leveldb-stores
[00000000011, 00000000012]
[zk: localhost:2181(CONNECTED) 3] get /activemq/leveldb-stores/0000000001
00000000011 00000000012
[zk: localhost:2181(CONNECTED) 3] get /activemq/leveldb-stores/00000000011
{"id":"activemq","container":null,"address":"tcp://192.168.67.180:63632","position":-1,"weight":1,"elected":"0000000011"}
cZxid = 0x1b0000001f
ctime = Thu Nov 05 22:32:29 CST 2020
mZxid = 0x1b0000002e
mtime = Thu Nov 05 22:39:39 CST 2020
pZxid = 0x1b0000001f
cversion = 0
dataVersion = 6
aclVersion = 0
ephemeralOwner = 0x2001314fdca0000
dataLength = 121
numChildren = 0
[zk: localhost:2181(CONNECTED) 4] get /activemq/leveldb-stores/00000000012
{"id":"activemq","container":null,"address":null,"position":-1,"weight":1,"elected":null}
cZxid = 0x1b00000026
ctime = Thu Nov 05 22:32:37 CST 2020
mZxid = 0x1b0000002c
mtime = Thu Nov 05 22:39:39 CST 2020
pZxid = 0x1b00000026
cversion = 0
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x10003ebda200004
dataLength = 89
numChildren = 0
[zk: localhost:2181(CONNECTED) 5]
此时activemq02(IP为192.168.67.180)成为master,登录管理界面测试