ActiveMQ高可用与集群搭建

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.如下图所示:

<persistenceAdapter>
     <!--<kahaDB directory="${activemq.data}/kahadb"/>-->
     <replicatedLevelDB
            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"
    />
</persistenceAdapter>

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:配置如下:

<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&amp;wireFormat.maxFrameSize=104857600"/>
  <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
</transportConnectors>

vi /usr/local/mqcluster/mq2/conf/activemq.xml:配置如下:

<transportConnectors>
  <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
  <transportConnector name="openwire" uri="tcp://0.0.0.0:61617?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  <transportConnector name="amqp" uri="amqp://0.0.0.0:5682?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  <transportConnector name="stomp" uri="stomp://0.0.0.0:61623?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1903?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  <transportConnector name="ws" uri="ws://0.0.0.0:61634?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
</transportConnectors>

vi /usr/local/mqcluster/mq3/conf/activemq.xml:配置如下:

<transportConnectors>
  <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
  <transportConnector name="openwire" uri="tcp://0.0.0.0:61618?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  <transportConnector name="amqp" uri="amqp://0.0.0.0:5692?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  <transportConnector name="stomp" uri="stomp://0.0.0.0:61633?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1913?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
  <transportConnector name="ws" uri="ws://0.0.0.0:61654?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
步骤五:

接着需要修改jetty的端口号(修改ACTIVEMQ_HOME/bin/jetty.xml文件).mq1依然使用默认端口8161,mq2使用8162,mq3使用8163端口:
vi /usr/local/mqcluster/mq1/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>

vi /usr/local/mqcluster/mq2/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="8162"/>
</bean>

vi /usr/local/mqcluster/mq3/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="8163"/>
</bean>
步骤六:

到这里为止,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的高可用的环境.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容