天天看点

ActiveMQ高可用集群部署方案

1.概述

1.1简介

ActiveMQ是分布式系统中重要的组件,主要解决应用耦合、异步消息、流量削锋等问题,是大型分布式系统不可缺少的中间件。在生产环境中为了保证让ActiveMQ能够持续工作,我们还需要为消息中间件服务搭建集群环境,从而在保证消息中间件服务可靠性和处理性能。

1.2集群模式概述

集群模式主要是为了解决ActiveMQ系统架构中的两个关键问题:高可用和高性能。

针对上述两种需求,AActiveMQ主要有如下两种集群模式分别对应:

  • Master-slave模式
  • Broker-Cluster模式

1.2.1Master-slave模式

Master-Slave集群由至少3个节点组成,一个Master节点,其他为Slave节点。只有Master节点对外提供服务,Slave节点处于等待状态。当主节点宕机后,从节点会推举出一个节点出来成为新的Master节点,继续提供服务。

ActiveMQ高可用集群部署方案

Master-Slave模式的部署方式,主要分为三种:

  • Shared Filesystem Master-Slave方式,如KahaDB,应用灵活、高效且安全。
  • Shared Database Master-Slave方式,基于共享数据库,跟第一种类似,性能会受限于数据库。
  • Replicated LevelDB Store方式,基于zookeeper + leveldb。是生产环境常用的方案。

1.2.2Broker-Cluster模式

Broker-Cluster部署方式中,各个broker通过网络互相连接,自动分发调用端请求,从而实现集群的负载均衡。Broker-Cluster集群连接到网络代理的方式,主要分为静态网络代理、动态网络代理,不同的网络代理方式也对应了不同的集群部署方式:

  • static Broker-Cluster
  • Dynamic Broker-Cluster

    在实际应用场景中static Broker-Cluster被大量使用。

ActiveMQ高可用集群部署方案

静态网络代理示意图

1.3集群部署规划

1.3.1集群架构

Master-Slave集群的优点是可以解决多服务热备的高可用问题,但缺点是无法解决负载均衡和分布式的问题。Broker-Cluster集群的优点是可以解决负载均衡和分布式的问题,但不支持高可用。

因此,把Master-Slave和Broker-Cluster两者相结合,就可以得到一个完美的解决方案:即又可以做到集群负载均衡又可以做到任何一个broker如果发生宕机,也不会影响提供服务,节点消息也不会“丢失”。

在这里我们可以选择部署6个ActiveMQ实例,把6个ActiveMQ实例分成两组(Group)。Group1的三个节点通过Master-Slave模式组成brokerA,group2的3个节点通过Master-Slave模式组成brokerB,并使得brokerA与brokerB组成Broker-Cluster集群。

ActiveMQ高可用集群部署方案

1.3.2服务器规划

一般情况下,生产环境需要多个ActiveMQ配置在多台服务器中,但是由于本次环境搭建仅用于学习测试,且本地环境的机器规格受限,所以接下来我们将会在两个docker容器中进行模拟,每个容器以3组端口运行3个ActiveMQ实例。因为是在一台机器上做实验,即使运行两个docker容器,也需要在宿主机映射对应的端口。所以不同的ActiveMQ实例需要有不同的端口配置,具体分配如下:

节点 IP openwire端口 admin端口
mq1 172.18.0.112 61616 8161
mq2 61617 8162
mq3 61618 8163
mq4 172.18.0.116 61619 8164
mq5 61620 8165
mq6 61621 8166

2.环境准备

2.1容器及网络环境准备

1.拉取centos7镜像

docker pull centos:7           

2.创建自定义docker网络

默认情况下启动的Docker容器,都是使用bridge网络,容器重启时,docker的IP就会发生改变,且不支持为容器指定固定IP。

因此我们需要基于bridge创建自定义网络。

docker network create --subnet=172.18.0.0/16 qqnetwork           

3.创建activemq所需容器

docker run -i -t --name mqbrokerAA -p 61616:61616 -p 61617:61617 -p 61618:61618 -p 8161:8161 -p 8162:8162 -p 8163:8163 --privileged=true --net qqnetwork --ip 172.18.0.112 -d centos:7

docker run -i -t --name mqbrokerBB -p 61619:61619 -p 61620:61620 -p 61621:61621 -p 8164:8164 -p 8165:8165 -p 8166:8166 --privileged=true --net qqnetwork --ip 172.18.0.116 -d centos:7           

2.2Java环境

ActiveMQ运行前需要确保已经安装配置jdk8的环境,这部分资料有很多,这里不再赘述。

3.集群部署

3.1搭建Master-Slave集群

3.1.1安装ActiveMQ

1.在/usr/local目录下创建mqcluster目录,然后在该目录中创建mq1,mq2,mq3的文件夹。

ActiveMQ高可用集群部署方案

2.将apache-activemq-5.15.3-bin.tar.gz压缩包的内容解压到这三个目录。

tar -zxvf apache-activemq-5.15.12-bin.tar.gz -C /usr/local/mqcluster/           

3.分别单独运行3个ActiveMQ实例,保证单独运行正常。

3.1.2配置集群

3.1.2.1配置节点名

ActiveMQ Master-Slave集群的broker必须有统一的brokername,在这里需要修改ACTIVEMQ_HOME/conf/activemq.xml文件,将3个节点的brokerName统一为“brokerA”。

<broker xmlns="http://activemq.apache.org/schema/core" brokerName="brokerA" dataDirectory="${activemq.data}">           
3.1.2.2持久化配置

ActiveMQ的持久化主要有如下几种方案:

  • 基于日志文件存储,如KahaDB
  • JDBC消息存储,如使用mysql将消息持久化
  • LevelDB消息存储

    这里采用KahaDB的方式,原理就是让参与高可用的所有节点共用一个数据文件目录,通过文件锁的方式来决定谁是master谁是slave。在这里需要做的就是将3个节点的数据目录配置成相同的即可。

修改ACTIVEMQ_HOME/conf/activemq.xml文件,3个节点均修改成如下配置即可。

<persistenceAdapter>
     <kahaDB directory="/usr/local/mqcluster/mq1/data/kahadb"/>
</persistenceAdapter>           
3.1.2.3TCP端口配置

实验环境暂时只用到tcp,所以只配置openwire,暂时将其它的端口配置注释掉。openwire默认为61616,同一个容器内端口不能重复,否则端口冲突,所以需要将mq1,mq2,mq3分别对应端口61616,61617,61618。

该配置也在ACTIVEMQ_HOME/conf/activemq.xml, 具体修改如下:

<transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
           
<transportConnector name="openwire" uri="tcp://0.0.0.0:61617?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>           
<transportConnector name="openwire" uri="tcp://0.0.0.0:61618?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>           
3.1.2.4Jetty端口配置

ActiveMQ使用jetty运行服务,与openwire同理,3个节点运行的端口必须不同。修改ACTIVEMQ_HOME/conf/jetty.xml,3个节点依次改为8161,8162,8163。

<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>           
<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>           
<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>           

3.1.3启动集群

至此,ActiveMQ高可用集群已经配置好了,然后分别启动mq1,mq2,mq3实例。

/usr/local/mqcluster/mq1/bin/activemq start
/usr/local/mqcluster/mq2/bin/activemq start
/usr/local/mqcluster/mq3/bin/activemq start           

如果配置正常,在后启动的两个节点的启动日志中会输出如下日志,表示已经有master锁定,自己将以slave角色运行。

注意:只有master节点接受请求,slave不接受请求,也无法使用管理界面。

3.2搭建Broker-Cluster集群

3.2.1搭建第二组Master-Slave集群

上面我们已经搭建好了一个Master-Slave集群,但仅仅是master-slave的话只能保证高可用,却无法做到负载均衡,如果mq因负载过大挂掉, master-slave也无法解决这种问题,所以就必须配置Broker-Cluster模式实现ActiveMQ集群的负载均衡。

此时,可以按照上述方式及前期的集群规划依次安装配置mq4/mq5/mq6,即可完成另一个Master-Slave集群。

3.2.2配置Broker-Cluster集群

Broker-Cluster部署方式中,“静态方式”在实际应用场景中被大量使用,因此我们这里采用静态uri方式,具体操作如下所示。

1.在group1中所有的节点修改ACTIVEMQ_HOME/conf/activemq.xml文件,添加如下配置链接group2(在persistenceAdapter标签前配置):

<networkConnectors>
    <networkConnector name="brokerB" uri="static:(tcp://172.18.0.116:61619,tcp://172.18.0.116:61620,tcp://172.18.0.116:61621)" duplex="true" />
</networkConnectors>           

需要注意,broker-cluster模式duplex默认为false,这种情况下broker-cluster可以实现消息分发,但消息只存在一个broker上。与此同时,也就意味着,一旦broker宕机,则可能会出现消息丢失。

这里我们配置duplex="true",当这个节点使用Network Bridge连接到其它目标节点后,将强制目标也建立Network Bridge进行反向连接。其目的在于让消息既能发送到目标节点,又可以通过目标节点接受消息。它相当于下面几行的效果:

<!-- 在group1中 -->  
<networkConnector name="group1-broker1" uri="static:(tcp://172.18.0.116:61619)" duplex="false" />  
<!-- 在group1中 -->  
<networkConnector name="group1-broker2" uri="static:(tcp://172.18.0.116:61620)" duplex="false" />  
<!-- 在group1中 -->  
<networkConnector name="group1-broker3" uri="static:(tcp://172.18.0.116:61621)" duplex="false" /> 
 
 
<!-- 在group2中 -->  
<networkConnector name="group2-broker1" uri="static:(tcp://172.18.0.112:61616)" duplex="false" />  
<!-- 在group2中 -->  
<networkConnector name="group2-broker2" uri="static:(tcp://172.18.0.112:61617)" duplex="false" />  
<!-- 在group2中 -->  
<networkConnector name="group2-broker3" uri="static:(tcp://172.18.0.112:61618)" duplex="false" />           

2.上一步配置duplex="true"后,group2中所有的节点则不需要再修改ACTIVEMQ_HOME/conf/activemq.xml文件,也不需要再链接group1。

到这里,我们就已经完成了ActiveMQ高可用+负载均衡的集群搭建。在下一篇文章我们将结合Java工程,完成对本次搭建的ActiveMQ系统的功能验证、高可用及负载均衡功能验证。