引入消息队列之后该如何保证其高可用性?
基于Zookeeper和LevelDB搭建ActiveMQ集群。集群仅提供主备方式的高可用集群功能,避免单点故障。

三种集群方式:基于sharedFileSystem共享文件系统(kahaDB默认)、基于JDBC、基于可复制的LevelDB

本次案例采用zookeeper+Replicated LevelDB Store

从ActiveMQ5.9开始,ActiveMQ的集群实现方式取消了传统的Master-Slave方式,
增加了基于Zookeeper+LevelDB的Master+Slave实现方式,从5.9版本后也是官网的推荐。

原理:
它使用Apache ZooKeeper协调集群中的哪个节点成为主节点。当选的主代理节点将启动并接受客户端连接。其他节点进入从模式并连接主节点并同步其持久状态。从节点不接受客户端连接。所有持久性操作都复制到连接的从站。如果主服务器去世,则具有最新更新的从服务器将升级为主服务器。然后可以将发生故障的节点重新联机,并将进入从属模式。
所有需要同步到磁盘的消息传递操作都将等待更新完成后再复制到法定仲裁节点。因此,如果将存储配置为,replicas="3"则仲裁大小为(3/2+1)=2。主服务器将更新存储在本地,并等待另外1个从服务器存储更新,然后再报告成功。考虑它的另一种方法是,存储将对复制节点的仲裁进行同步复制,对任何其他节点进行异步复制复制。
当选出一个新的主节点时,您还至少需要有一定数量的联机节点才能找到更新最新的节点。更新最新的节点将成为新的主节点。因此,建议您至少使用3个副本节点运行,以便可以在不造成服务中断的情况下关闭一个副本节点。

1、环境和版本

Centos7、JDK1.8以上版本、Zookeeper-3.4.9、apache-activemq-5.15.9

2.关闭防火墙并保证win可以ping通过ActiveMQ服务器
3.要求具备ZK集群并可以成功启动
4.集群部署规划列表

java 链接 activemq集群 activemq集群原理_客户端


启动Zookeeper集群服务:此处采用的是docker的方式

5.创建3台集群目录
mkdir /mq_cluster/ #创建集群目录
cp -r /opt/apache-activemq-5.15.9 mq_node01 #创建第1个node节点
cp -r mq_node01  mq_node02 #创建第2个node节点
cp -r mq_node01  mq_node03 #创建第3个node节点
6.修改管理控制台端口

编辑每个节点下的conf/jetty.xml配置文件:修改管理控制台的端口,node01节点可以不修改

java 链接 activemq集群 activemq集群原理_java 链接 activemq集群_02

7.hostname名字映射

编辑/etc/hosts文件进行域名映射:该配置文件和Windows下的hosts文件类似

192.168.2.107 mq-server
8.ActiveMQ集群配置

修改三个节点的brokerName,使它们完全一样

java 链接 activemq集群 activemq集群原理_服务器_03


修改三个节点的持久化方式为LevelDB:

node1

<persistenceAdapter>
	<replicatedLevelDB 
		directory="${activemq.data}/leveldb"
		replicas="3"
		bind="tcp://0.0.0.0:63631"
		zkAddress="localhost:2191,localhost:2192,localhost:2193"
		hostname="mq-server"
		sync="local_disk"
		zkPath="/activemq/leveldb-stores"/>
</persistenceAdapter>

node2

<persistenceAdapter>
	<replicatedLevelDB 
		directory="${activemq.data}/leveldb"
		replicas="3"
		bind="tcp://0.0.0.0:63632"
		zkAddress="localhost:2191,localhost:2192,localhost:2193"
		hostname="mq-server"
		sync="local_disk"
		zkPath="/activemq/leveldb-stores"/>
</persistenceAdapter>

node3

<persistenceAdapter>
	<replicatedLevelDB 
		directory="${activemq.data}/leveldb"
		replicas="3"
		bind="tcp://0.0.0.0:63633"
		zkAddress="localhost:2191,localhost:2192,localhost:2193"
		hostname="mq-server"
		sync="local_disk"
		zkPath="/activemq/leveldb-stores"/>
</persistenceAdapter>

注意:
   zkAddress的值即为上面的zk集群的地址
   hostName的值为我们做的域名映射的域名
   repicas的值为节点的个数

9.修改各节点的消息端口

第1个节点可不做改动

java 链接 activemq集群 activemq集群原理_服务器_04

java 链接 activemq集群 activemq集群原理_docker_05

10.按顺序启动3个AtiveMQ节点,到这步前提是zk集群已经成功启动运行

按顺序启动这3个MQ节点,可以采用如下的Shell脚本(mq_start.sh)进行启动:启动之前务必保证ZK集群已经正常启动

#!/bin/sh

cd /mq_cluster/mq_node01/bin
./activemq start

cd /mq_cluster/mq_node02/bin
./activemq start

cd /mq_cluster/mq_node03/bin
./activemq start

访问:http://192.168.2.107:8161/admin/

注意:
  需要关闭防火墙保证Windows可以ping通ActiveMQ所在的服务器
  此时只能访问8161这个端口的服务,因为Shell脚本中它是最先启动的,是此时的Master,剩下的两个Slave是不能被访问的,只有当Master宕机后被推选为Master的Slave才可以被访问。总而言之,只有Master可以被访问
  如果是在虚拟机上使用docker的方式搭建集群,在访问管理控制台时很可能会报错,查看后台日志的错误信息是:no space left on device,此时可以尝试清理下docker的空间

ZK集群的节点状态查看

通过zkCli连接到zk集群中任意一个服务(也可以在Windows下使用zkCli客户端连接,前提是网络相通),可以查看到集群中的每个mq服务的状态:因为我在Linux虚拟机上采用docker的方式安装的zk,没有安装zk客户端,因此此处在Windows环境下进行查看


java 链接 activemq集群 activemq集群原理_服务器_06

客户端连接MQ集群
public static final String ACTIVEMQ_URL = "failover:(tcp://192.168.2.107:61616,tcp://192.168.2.107:61617,tcp://192.168.2.107:61618)?randomize=false";