ActiveMQ的集群多种部署方式

ActiveMQ的多种部署方式

         单点的ActiveMQ作为企业应用无法满足高可用和集群的需求,所以ActiveMQ提供了master-slave、broker cluster等多种部署方式,但通过分析多种部署方式之后我认为需要将两种部署方式相结合才能满足我们公司分布式和高可用的需求,所以后面就重点将解如何将两种部署方式相结合。
1、Master-Slave部署方式
1)shared filesystem Master-Slave部署方式

         主要是通过共享存储目录来实现master和slave的热备,所有的ActiveMQ应用都在不断地获取共享目录的控制权,哪个应用抢到了控制权,它就成为master。

         多个共享存储目录的应用,谁先启动,谁就可以最早取得共享目录的控制权成为master,其他的应用就只能作为slave。

p2.png
2)shared database Master-Slave方式

         与shared filesystem方式类似,只是共享的存储介质由文件系统改成了数据库而已。
3)Replicated LevelDB Store方式

         这种主备方式是ActiveMQ5.9以后才新增的特性,使用ZooKeeper协调选择一个node作为master。被选择的master broker node开启并接受客户端连接。

其他node转入slave模式,连接master并同步他们的存储状态。slave不接受客户端连接。所有的存储操作都将被复制到连接至Master的slaves。

如果master死了,得到了最新更新的slave被允许成为master。fialed node能够重新加入到网络中并连接master进入slave mode。所有需要同步的disk的消息操作都将等待存储状态被复制到其他法定节点的操作完成才能完成。所以,如果你配置了replicas=3,那么法定大小是(3/2)+1=2. Master将会存储并更新然后等待 (2-1)=1个slave存储和更新完成,才汇报success。至于为什么是2-1,熟悉Zookeeper的应该知道,有一个node要作为观擦者存在。

单一个新的master被选中,你需要至少保障一个法定node在线以能够找到拥有最新状态的node。这个node将会成为新的master。因此,推荐运行至少3个replica nodes,以防止一个node失败了,服务中断。

2、Broker-Cluster部署方式

         前面的Master-Slave的方式虽然能解决多服务热备的高可用问题,但无法解决负载均衡和分布式的问题。Broker-Cluster的部署方式就可以解决负载均衡的问题。

         Broker-Cluster部署方式中,各个broker通过网络互相连接,并共享queue。当broker-A上面指定的queue-A中接收到一个message处于pending状态,而此时没有consumer连接broker-A时。如果cluster中的broker-B上面由一个consumer在消费queue-A的消息,那么broker-B会先通过内部网络获取到broker-A上面的message,并通知自己的consumer来消费。
1)static Broker-Cluster部署

         在activemq.xml文件中静态指定Broker需要建立桥连接的其他Broker:

1、  首先在Broker-A节点中添加networkConnector节点:

<networkConnectors>

                <networkConnector   uri="static:(tcp:// 0.0.0.0:61617)"duplex="false"/>

</networkConnectors>

2、  修改Broker-A节点中的服务提供端口为61616:

<transportConnectors>

         <transportConnectorname="openwire"uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>

</transportConnectors>

3、  在Broker-B节点中添加networkConnector节点:

<networkConnectors>

                <networkConnector   uri="static:(tcp:// 0.0.0.0:61616)"duplex="false"/>

</networkConnectors>

4、  修改Broker-A节点中的服务提供端口为61617:

<transportConnectors>

         <transportConnectorname="openwire"uri="tcp://0.0.0.0:61617?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>

</transportConnectors>

5、分别启动Broker-A和Broker-B。
2)Dynamic Broker-Cluster部署

         在activemq.xml文件中不直接指定Broker需要建立桥连接的其他Broker,由activemq在启动后动态查找:

1、  首先在Broker-A节点中添加networkConnector节点:

<networkConnectors>

                <networkConnectoruri="multicast://default"

           dynamicOnly="true"

           networkTTL="3"

           prefetchSize="1"

           decreaseNetworkConsumerPriority="true" />

</networkConnectors>

2、修改Broker-A节点中的服务提供端口为61616:

<transportConnectors>

         <transportConnectorname="openwire"uri="tcp://0.0.0.0:61616? " discoveryUri="multicast://default"/>

</transportConnectors>

3、在Broker-B节点中添加networkConnector节点:

<networkConnectors>

                <networkConnectoruri="multicast://default"

           dynamicOnly="true"

           networkTTL="3"

           prefetchSize="1"

           decreaseNetworkConsumerPriority="true" />

</networkConnectors>

4、修改Broker-B节点中的服务提供端口为61617:

<transportConnectors>

         <transportConnectorname="openwire"uri="tcp://0.0.0.0:61617" discoveryUri="multicast://default"/>

</transportConnectors>

5、启动Broker-A和Broker-B
2、Master-Slave与Broker-Cluster相结合的部署方式

         可以看到Master-Slave的部署方式虽然解决了高可用的问题,但不支持负载均衡,Broker-Cluster解决了负载均衡,但当其中一个Broker突然宕掉的话,那么存在于该Broker上处于Pending状态的message将会丢失,无法达到高可用的目的。

         由于目前ActiveMQ官网上并没有一个明确的将两种部署方式相结合的部署方案,所以我尝试者把两者结合起来部署:

         p4.png
1、部署的配置修改

         这里以Broker-A + Broker-B建立cluster,Broker-C作为Broker-B的slave为例:

1)首先在Broker-A节点中添加networkConnector节点:

<networkConnectors>

                <networkConnector   uri="masterslave:(tcp://0.0.0.0:61617,tcp:// 0.0.0.0:61618)" duplex="false"/>

</networkConnectors>

2)修改Broker-A节点中的服务提供端口为61616:

<transportConnectors>

         <transportConnectorname="openwire"uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>

</transportConnectors>

3)在Broker-B节点中添加networkConnector节点:

<networkConnectors>

                <networkConnector   uri="static:(tcp:// 0.0.0.0:61616)"duplex="false"/>

</networkConnectors>

4)修改Broker-B节点中的服务提供端口为61617:

<transportConnectors>

         <transportConnectorname="openwire"uri="tcp://0.0.0.0:61617?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>

</transportConnectors>

5)修改Broker-B节点中的持久化方式:

      <persistenceAdapter>

           <kahaDB directory="/localhost/kahadb"/>

        </persistenceAdapter>

6)在Broker-C节点中添加networkConnector节点:

<networkConnectors>

                <networkConnector   uri="static:(tcp:// 0.0.0.0:61616)"duplex="false"/>

</networkConnectors>

7)修改Broker-C节点中的服务提供端口为61618:

<transportConnectors>

         <transportConnectorname="openwire"uri="tcp://0.0.0.0:61618?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>

</transportConnectors>

8)修改Broker-B节点中的持久化方式:

      <persistenceAdapter>

           <kahaDB directory="/localhost/kahadb"/>

       </persistenceAdapter>

9)分别启动broker-A、broker-B、broker-C,因为是broker-B先启动,所以“/localhost/kahadb”目录被lock住,broker-C将一直处于挂起状态,当人为停掉broker-B之后,broker-C将获取目录“/localhost/kahadb”的控制权,重新与broker-A组成cluster提供服务。

-----------------------------------------------------------------------------------------------------

ActiveMQ的集群与高可用

针对大量的消息吞吐量、对MQ可用性要求非常严格的场景、或者非常复杂的消息处理关系情况下,单个MQ实例通常已经无法满足我们的需要,这时候ActiveMQ的集群和高可用方案就对我们很重要了。
1.client的集群

对消费者来说,使用queue即可做到某种意义上的消费者集群,所有消费者共同处理同一类消息。

非持久订阅的topic,这种功能没有实现。但是持久订阅的topic,可以通过Composite Destination机制转换成针对具体的持久消费者的专用queue,从而实现多个client共同处理同一类消息。参见:http://blog.csdn.net/kimmking/article/details/9773085

需要注意的是,如果缓存了consumer(例如spring DMLC+cache consumer)情况下使用了prefetch,多个consumer间可能导致消息顺序混乱。见:http://activemq.apache.org/what-is-the-prefetch-limit-for.html
2.client的高可用

在客户端来说,最简单的高可用方案就是内置的failover机制。它帮助我们在客户端实现:

    在某个broker故障时,自动使用其他备用broker
    强大的断线重连机制,哪怕是只有一个broker时,也可以用来在broker down掉重启后,客户端重新连接上

断线重连的配置和参数说明参见:http://activemq.apache.org/failover-transport-reference.html
3.broker的集群

broker端,典型的集群方式就是Network Connector,通过桥接的方式把多个broker,一个个的串起来,整个broker网络就可以作为一个整体,协同工作。

每个connect上去的broker,都会自动在被连接的broker上创建一个client connecttion,并通过Advisory机制共享自己的消费者列表,从而使得消息可以跨过broker在这个网络上自由流动。也可以设置duplex为true使得这个连通变为双向的对等网络。在BrokerA上配置一个指向BrokerB上的network connector,则连接到BrokerA上的各个ConsumerA1、ConsumerA2、ConsumerA3,都可以消费BrokerB上的QueueB里的消息。默认这三个消费者都被当做一个消费者来看待,即如果BrokerB上有一个ConsumerB1消费。

详细参见:http://blog.csdn.net/kimmking/article/details/8440150

其实个人感觉更好的集群方式是增加类似kafka和metaq的partition,然后使用zk作为配置中心来协调各个不同的broker实例、以及不同的partition来协同工作,使得broker的读写都可以分散进行。
4.broker的高可用

Broker端的高可用主要是Master-Slave实现的冷备,需要结合客户端的failover来用。

5.8.0以前的版本,支持三种Master-Slave:

    基于共享储存的Master-Slave:多个broker实例使用一个存储文件,谁拿到文件锁就是master,其他处于待启动状态,如果master挂掉了,某个抢到文件锁的slave变成master。由于使用的还是master的存储文件,所以数据好似一致的。
    基于JDBC的Master-Slave:使用同一个数据库,拿到LOCK表的写锁的broker成为master,机制同上。
    Pure Master-Slave:Slave的broker,简单的从Master复制数据和状态,问题较多,已被废弃。

5.9.0版本以后,Pure Master-Slave机制被废弃,新添加了基于zk的复制LevelDB存储Master-Slave机制。

此外还有一种可选方式就是,使用某种存储复制技术,比如Raid、或是DB的replication等等机制来同步存储,在故障的时候,使用这个复制的存储恢复broker。

详细参见:http://activemq.apache.org/masterslave.html

基于zookeeper 的集群


高可用的原理:使用ZooKeeper(集群)注册所有的ActiveMQ Broker。只有其中的一个Broker 可以提供 服务,被视为Master,其他的Broker 处于待机状态,被视为Slave。如果Master 因故障而不能提供服务,

ZooKeeper 会从 Slave中选举出一个 Broker充当 Master。

Slave 连接 Master并同步他们的存储状态,Slave不接受客户端连接。所有的存储操作都将被复制到

连接至 Master 的Slaves。如果 Master 宕了,得到了最新更新的 Slave 会成为 Master。故障节点在恢复后

会重新加入到集群中并连接 Master 进入Slave 模式。

所有需要同步的 disk 的消息操作都将等待存储状态被复制到其他法定节点的操作完成才能完成。所以,如果你配置了replicas=3,那么法定大小是(3/2)+1=2。Master 将会存储并更新然后等待 (2-1)=1 个Slave存储和更新完成,才汇报 success。至于为什么是 2-1,熟悉 Zookeeper 的应该知道,有一个 node要作为观擦者存在。当一个新的Master 被选中,你需要至少保障一个法定node 在线以能够找到拥有最新 状态的node。这个node 可以成为新的Master。因此,推荐运行至少3 个replica nodes,以防止一个node失败了,服务中断。(原理与 ZooKeeper 集群的高可用实现方式类似)


猜你喜欢

转载自haidaoqi3630.iteye.com/blog/2317552