ActiveMQ的高可用性架构是基于Master/Slave 模型的,Master/Slave模式的搭建有好几种方式:
1)Shared File System Master Slave 使用共享文件系统的方式
2)JDBC Master Slave 使用数据库作为持久化存储
3)基于zookeeper 方式搭建
我们采取的是zookeeper的方式搭建Active高可用环境:
步骤一:
确保已经安装好jdk8的环境和zookeeper的环境.如果没装好的同学,找之前的文档装一装.
步骤二:
正常来说,多个ActiveMQ应该配置在多台服务器中的,但是做实验我们就只在一台CentOS中来模拟,每个ActiveMQ的端口不一致.在/usr/local目录下创建mqcluster目录,然后在该目录中创建mq1,mq2,mq3的文件夹.将apache-activemq-5.15.3-bin.tar.gz压缩包的内容解压到这三个目录.
步骤三:
首先修改每个ActiveMQ的持久化方式(修改ACTIVEMQ_HOME/conf/activemq.xml文件),ActiveMQ默认使用的是KahaDB作为持久化存储数据的,我们修改成levelDB.如下图所示:
directory="${activemq.data}/leveldb"
replicas="3"
bind="tcp://0.0.0.0:0"
zkAddress="192.168.122.129:2181"
zkPassword=""
hostname="localhost"
sync="local_disk"
zkPath="/activemq/leveldb-stores/group1"
/>
directory:levelDB持久化路径
replicas=“3”: ActiveMQ实例的节点数,它需要满足2N+1
bind:当这个节点成为Master, 它会绑定配置好的地址和端口来履行主从复制协议(官方建议不要改动)
zkAddress:zk的地址,这里可以配置集群
sync: 在认为消息被消费完成前, 同步信息所存贮的策略,如果有多种策略用逗号隔开, ActiveMQ会选择较强的策略(local_mem, local_disk则肯定选择存贮在本地硬盘)
zkPath : ZooKeeper选举信息交换的存贮路径
步骤四:
针对mq2和mq3的目录需要修改一下对应的端口.端口分配如下所示:
节点
openwire端口
amqp端口
stomp端口
mqtt端口
ws端口
admin端口
mq1
61616
5672
61613
1883
61614
8161
mq2
61617
5682
61623
1903
61634
8162
mq3
61618
5692
61633
1923
61654
8163
vi /usr/local/mqcluster/mq1/conf/activemq.xml:配置如下:
vi /usr/local/mqcluster/mq2/conf/activemq.xml:配置如下:
vi /usr/local/mqcluster/mq3/conf/activemq.xml:配置如下:
步骤五:
接着需要修改jetty的端口号(修改ACTIVEMQ_HOME/bin/jetty.xml文件).mq1依然使用默认端口8161,mq2使用8162,mq3使用8163端口:
vi /usr/local/mqcluster/mq1/conf/jetty.xml:配置如下:
init-method="start">
vi /usr/local/mqcluster/mq2/conf/jetty.xml:配置如下:
init-method="start">
vi /usr/local/mqcluster/mq3/conf/jetty.xml:配置如下:
init-method="start">
步骤六:
到这里为止,ActiveMQ的高可用就已经配置好了,需要先把zookeeper先开启.(注意要把防火墙关闭),分别启动mq1,mq2,mq3程序.
/usr/local/mqcluster/mq1/bin/linux-x86-64/activemq start
/usr/local/mqcluster/mq2/bin/linux-x86-64/activemq start
/usr/local/mqcluster/mq3/bin/linux-x86-64/activemq start
可以登录zookeeper客户端可以查看到对应的节点.
其中elected不为空的节点表示为Master,由该activemq对外提供服务。
接着我们来测试一下:
生产端:
/**
* Created by lanxw
*/
public class Producer {
public static void main(String[] args) throws Exception {
//第一步:建立ConnectionFactory工厂对象,需要填入用户名,密码,以及要连接的地址.均使用默认即可,默认端口为tcp://localhost:61616
ConnectionFactory factory = new ActiveMQConnectionFactory(
"lanxw",
"lanxw",
"failover:(tcp://192.168.122.129:61616,tcp://192.168.122.129:61617,tcp://192.168.122.129:61618)?randomize=false"
);
//第二步:通过ConnectionFactory工厂对象我们创建一个Connection连接,并且调用Connection的start方法开启连接,Connection默认是关闭的.
Connection connection = factory.createConnection();
connection.start();
//第三步:通过Connection对象创建Session会话(上下文环境对象),用于接受信息,参数配置1为是否启动事务,参数配置2为签收模式,一般我们设置自动签收.
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//第四步:通过session创建Destination对象,指的是一个客户端用户指定生产者消息目标和消费消息的来源的对象.在PTP模式中,Destination称作Queue即队列;在Pub/Sub模式,Destination被称作Topic即主体.在程序中可以使用多个Queue和Topic.
Queue destination = session.createQueue("test");
//第五步:我们需要通过Session对象创建消息的发送和接受对象(生产者和消费者)MessageProducer/MessageConsumer
MessageProducer producer = session.createProducer(null);
TextMessage msg;
for(int i = 0;i<3;i++){
msg = session.createTextMessage("这是队列消息" + i);
//第六步:我们可以使用MessageProducer的setDeliveryMode方法为其设置持久化特性和非持久化特性(DeliveryMode),我们稍后详细介绍.
producer.send(destination,msg);
}
//session.commit();
//第七步:最后我们使用JMS规范的TextMessage形式创建数据(通过Session对象),并用MessageProducer的send方法发送数据.同理客户端使用receive方法进行接接收数据,最后不要忘记关闭Connection连接.
if(connection!=null){
connection.close();
}
}
}
消费端:
/**
* Created by lanxw
*/
public class Cusumer {
public static void main(String[] args) throws JMSException {
//第一步:建立ConnectionFactory工厂对象,需要填入用户名,密码,以及要连接的地址.均使用默认即可,默认端口为tcp://localhost:61616
ConnectionFactory factory = new ActiveMQConnectionFactory(
"lanxw",
"lanxw",
"failover:(tcp://192.168.122.129:61616,tcp://192.168.122.129:61617,tcp://192.168.122.129:61618)?randomize=false");
//第二步:通过ConnectionFactory工厂对象我们创建一个Connection连接,并且调用Connection的start方法开启连接,Connection默认是关闭的.
Connection connection = factory.createConnection();
connection.start();
//第三步:通过Connection对象创建Session会话(上下文环境对象),用于接受信息,参数配置1为是否启动事务,参数配置2为签收模式,一般我们设置自动签收.
Session session = connection.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
//第四步:通过session创建Destination对象,指的是一个客户端用户指定生产者消息目标和消费消息的来源的对象.在PTP模式中,Destination称作Queue即队列;在Pub/Sub模式,Destination被称作Topic即主体.在程序中可以使用多个Queue和Topic.
Destination destination = session.createQueue("test");
//第五步:通过session创建消费者对象
MessageConsumer consumer = session.createConsumer(destination);
while (true){
TextMessage msg = (TextMessage) consumer.receive();
System.out.println(msg.getText());
}
}
}
测试:
我们停掉任何一台ActiveMQ,发现依然可以发送消息和接收消息.说明我们已经搭建好ActiveMQ的高可用的环境.