ActiveMQ(七)_伪集群和主从高可用使用

 
一、本文目的
        介绍如何在同一台虚拟机上搭建高可用的Activemq服务,集群数量包含3个Activemq,当Activemq可用数>=2时,整个集群可用。
        本文Activemq的集群数量为3个,分别命名为mq1,mq2,mq3
 
二、概念介绍
1、伪集群
      集群搭建在同一台虚拟机上,3个Activemq分别使用不同的端口提供服务,启用1个为Master,其它2个为Slaver,同一时间仅Master队列提供服务
2、高可用
      3个Activemq服务, 同一时间仅Master队列提供服务,当Master队列挂掉后,其它2个Slaver自动选举出1个成为Master,整个队列服务依然可用。当挂掉的队列重新恢复后,自动加入集群。当集群仅剩下1个队列时,整个队列不可用。
3、Activemq集群数据存储方式
      a) kahaDB:文件共享,默认方式
      b) JDBC:数据库共享,支持MySql、Sql Server、Oracle等
      c) LevelDB:数据共享, 本文使用方式,比kahaDB更快,基于索引
 
三、Activemq伪集群的搭建
1、Activemq的端口介绍
       Activemq默认主要使用2个端口,8161(Web管理控制台端口)、61616(提供消息队列服务的端口),如果需要搭建集群,还需要开放集群间通讯的端口(主要用于选举Master)
 
2、Activemq集群端口的分配
  Web管理控制台 消息服务接口 集群通讯接口
mq1 8161 51511 61601
mq2 8162 51512 61602
mq3 8163 51513 61603
服务接口没有使用默认的61611是因为activemq默认还会使用61613,61614等端口,如何开放端口及配置控制台端口请自行百度
 
3、修改activemq配置
a) 安装activemq,本文使用Activemq版本为5.11.1,安装过程略
b) 修改配置文件activemq.xml,路径为conf/activemq.xml
     1、broker(所有activemq的brokerName必须一致,才能加入同一个集群)
1
< broker xmlns = "http://activemq.apache.org/schema/core" brokerName = "V1MQ" dataDirectory = "${activemq.data}" >

    2、配置levelDB,加载<broker>节点内

           bind:集群间通讯的ip和端口

           zkAddress:ZooKeeper地址,多个可用,逗号分隔

           hostname:主机名,可在/etc/hosts中进行配置

           zkPath:zkPath目录,可在ZooInspetor中进行查看

1
2
3
4
5
6
7
8
9
10
11
< persistenceAdapter >
          <!-- kahaDB directory="${activemq.data}/kahadb"/ -->
          < replicatedLevelDB
              directory = "${activemq.data}/leveldb"
              replicas = "3"
              bind = "tcp://127.0.0.1:61601"
              zkAddress = "192.168.146.130:2181"
              hostname = "V1"
              zkPath = "/activemq/leveldb-stores"
              />
      </ persistenceAdapter >

4、启动activemq

      /usr/local/src/activemq1/bin/activemq start

      可通过/usr/local/src/activemq1/data/activemq.log查看启动日志

 

5、关于管控台

       虽然3个activemq都启动了,但是同一时间只有Master对应的管控台可用,Slaver对应的管控台不可用

 

四、结合ZooInspector测试(推荐使用dubbokeeper中查看zookeeper的一个UI插件,https://github.com/dubboclub/dubbokeeper)

1、打开ZooInspector(可自行搜索下载或从群中下载),输入ZooKeeper地址进行监控,如果3个activemq都启动成功,则显示如下:

2、Java测试代码

       代码可参考:http://www.cnblogs.com/gossip/p/5970090.html

       a) 配置集群IP(这里3个activemq的端口分别是51511,51512,51513)

1
2
3
4
5
6
7
8
<!-- 配置JMS连接工厂 -->
< bean id = "connectionFactory" class = "org.apache.activemq.ActiveMQConnectionFactory" >
     < property name = "brokerURL" value = "failover:(tcp://192.168.146.129:51511,tcp://192.168.146.129:51512,tcp://192.168.146.129:51513)" />
     <!--解决接收消息抛出异常:javax.jms.JMSException: Failed to build body from content. Serializable class not available to broke-->
     < property name = "trustAllPackages" value = "true" />
     <!-- 是否异步发送 -->
     < property name = "useAsyncSend" value = "true" />
</ bean >

        b)  测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Test
   public void produceMsg_DefaultQueue() {
       for ( int i = 0 ; i < 10000 ; i++) {
           final String msg = "序号:" +String.valueOf(i) + " " + "这里是向默认队列发送的消息" + new Date().toString();
           System.out.println(msg);
 
           String destination = jmsTemplate.getDefaultDestination().toString();
           jmsTemplate.send( new MessageCreator() {
               public Message createMessage(Session session) throws JMSException {
                   return session.createTextMessage(msg);
               }
           });
 
           try {
               Thread.sleep( 300 );
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
   }

3、启动Java程序并发送消息

 

4、关闭Master队列(注意此时的Master队列为mq2)

a)   此时的ZooInspetor

 

5、重启mq2队列(重启后mq2加入队列成为Slaver,但是mq1还是Master,队列不受影响)

 

6、关闭mq1、mq2,仅剩mq3(由于只有一个队列,无法进行选举,所以整个队列都无法提供服务)


 

7、重启mq1(重启mq1后,mq1和mq3选举了Master队列,从而重新对外提供服务)

a) ZooInspecto显示mq1被选举为Master

b) 程序重新向队列消息,数据并没有中断 

 

五、总结

        本文演示了activemq伪集群的搭建过程及高可用的测试过程,通过举一反三可以将activemq部署到不同的机器上,从而实现相同的功能。

        遗留问题:ZooInspetor的activemq编号是自动生成的,很难发现其对应的队列,请问有没有可以自定义编号的方法,谢谢。

 

六、参考资料

1、http://www.cnblogs.com/gossip/p/5970090.html

2、http://activemq.apache.org/replicated-leveldb-store.html