ActiveMQ高可用+负载均衡集群的安装、配置、高可用[ZooKeeper + LevelDB + Static discovery](多节点)

前言:从ActiveMQ 5.9开始,ActiveMQ的集群实现方式取消了传统的Master-Slave方式,增加了基于ZooKeeper + LevelDB的Master-Slave实现方式,其他两种方式目录共享和数据库共享依然存在。

一、三种集群方式的对比:

(1)基于共享文件系统(KahaDB,默认):

<persistenceAdapter>
<kahaDB directory="${activemq.data}/kahadb"/>
</persistenceAdapter>

(2)基于JDBC:

<bean id="mysql-ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/amq?relaxAutoCommit=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="maxActive" value="20"/>  
<property name="poolPreparedStatements" value="true"/>
</bean>
<persistenceAdapter>
   <jdbcPersistenceAdapter dataDirectory="${activemq.data}" dataSource="#mysql-ds" 
		createTablesOnStartup="false"/>
</persistenceAdapter>

(3)基于可复制的LevelDB(本教程采用这种集群方式):

  • LevelDB是Google开发的一套用于持久化数据的高性能类库。LevelDB并不是一种服务,用户需要自行实现Server。是单进程的服务,能够处理十亿级别规模Key-Value型数据,占用内存小。
<persistenceAdapter>
    <replicatedLevelDB 
        directory="${activemq.data}/leveldb"
        replicas="3"
        bind="tcp://0.0.0.0:62621"
        zkAddress="localhost:2181,localhost:2182,localhost:2183" 
        hostname="localhost"
        zkPath="/activemq/leveldb-stores"
    />
 </persistenceAdapter>

二、基于ZooKeeper和LevelDB搭建ActiveMQ集群。集群仅提供主备方式的高可用集群功能,避免单点故障,没有负载均衡功能。

  • 官方文档:http://activemq.apache.org/replicated-leveldb-store.html
  • 集群原理图:
  • 在这里插入图片描述
  • 高可用的原理
  • 使用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集群的高可用实现方式类似)

1、ActiveMQ集群部署规划:

  • 环境:CentOS 6.6 x64 、 JDK7
  • 版本:ActiveMQ 5.11.1
  • ZooKeeper集群环境:192.168.0.222:2181,192.168.0.223:2182,192.168.0.224:2183
主机集群端口消息端口管控台端口节点安装目录
192.168.0.22262621515118161/home/hk/activemq/node-01
192.168.0.22362622515128162/home/hk/activemq/node-02
192.168.0.22462623515138163/home/hk/activemq/node-03

2、防火墙打开对应的端口

## node-01
-A INPUT -m state --state NEW -m tcp -p tcp --dport 8161 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 51511 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 61621 -j ACCEPT
## node-02
-A INPUT -m state --state NEW -m tcp -p tcp --dport 8162 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 51512 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 61622 -j ACCEPT
## node-03
-A INPUT -m state --state NEW -m tcp -p tcp --dport 8163 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 51513 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 61623 -j ACCEPT

3、分别在三台主机中创建/home/hk/activemq目录

$ mkdir /home/hk/activemq
上传apache-activemq-5.11.1-bin.tar.gz到/home/hk/activemq目录

4、解压并按节点命名

$ cd /home/hk/activemq
$ tar -xvf apache-activemq-5.11.1-bin.tar.gz
$ mv apache-activemq-5.11.1 node-0X   #(X代表节点号1、2、3,下同)

5、修改管理控制台端口(默认为8161)可在conf/jetty.xml中修改,如下:

Node-01管控台端口:

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

Node-02管控台端口:

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

Node-03管控台端口:

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

6、集群配置:

  • 在3个ActiveMQ节点中配置conf/activemq.xml中的持久化适配器。修改其中bind、zkAddress、hostname和zkPath。注意:每个ActiveMQ的BrokerName必须相同,否则不能加入集群。
Node-01中的持久化配置:
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="DubboEdu" dataDirectory="${activemq.data}">
	<persistenceAdapter>
		<!-- kahaDB directory="${activemq.data}/kahadb"/ -->
	<replicatedLevelDB
		directory="${activemq.data}/leveldb"
		replicas="3"
		bind="tcp://0.0.0.0:62621"
		zkAddress="192.168.0.222:2181,192.168.0.223:2182,192.168.0.224:2183"
		hostname="edu-zk-01"
		zkPath="/activemq/leveldb-stores"
	/>
	</persistenceAdapter>
</broker>
Node-02中的持久化配置:
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="DubboEdu" dataDirectory="${activemq.data}">
	<persistenceAdapter>
		<!-- kahaDB directory="${activemq.data}/kahadb"/ -->
		<replicatedLevelDB
			directory="${activemq.data}/leveldb"
			replicas="3"
			bind="tcp://0.0.0.0:62622"
			zkAddress="192.168.0.222:2181,192.168.0.223:2182,192.168.0.224:2183"
			hostname="edu-zk-02"
			zkPath="/activemq/leveldb-stores"
    	  />
	</persistenceAdapter>
</broker>
Node-03中的持久化配置:
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="DubboEdu" dataDirectory="${activemq.data}">
	<persistenceAdapter>
		<!-- kahaDB directory="${activemq.data}/kahadb"/ -->
		<replicatedLevelDB
			directory="${activemq.data}/leveldb"
			replicas="3"
			bind="tcp://0.0.0.0:62623"
			zkAddress="192.168.0.222:2181,192.168.0.223:2182,192.168.0.224:2183"
			hostname="edu-zk-03"
			zkPath="/activemq/leveldb-stores"
		/>
	</persistenceAdapter>
</broker>

修改各节点的消息端口[openwire](注意,避免端口冲突):

Node-01中的消息端口配置:
<transportConnectors>
   <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
   <transportConnector name="openwire" uri="tcp://0.0.0.0:51511?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>
Node-02中的消息端口配置:
<transportConnectors>
   <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
   <transportConnector name="openwire" uri="tcp://0.0.0.0:51512?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>
Node-03中的消息端口配置:
<transportConnectors>
   <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
   <transportConnector name="openwire" uri="tcp://0.0.0.0:51513?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>

7、按顺序启动3个ActiveMQ节点:

$ /home/hk/activemq/node-01/bin/activemq start
$ /home/hk/activemq/node-02/bin/activemq start
$ /home/hk/activemq/node-03/bin/activemq start
监听日志:
$ tail -f /home/hk/activemq/node-01/data/activemq.log
$ tail -f /home/hk/activemq/node-02/data/activemq.log
$ tail -f /home/hk/activemq/node-03/data/activemq.log

8、集群的节点状态分析:

  • 集群启动后对ZooKeeper数据的抓图,可以看到ActiveMQ的有3个节点,分别是00000000000,00000000001,00000000002。
  • 以下第一张图展现了00000000000的值,可以看到elected的值是不为空,说明这个节点是Master,其他两个节点是Slave。
  • 在这里插入图片描述
  • 在这里插入图片描述
  • 在这里插入图片描述

9、集群可用性测试

  • ActiveMQ的客户端只能访问Master的Broker,其他处于Slave的Broker不能访问。所以客户端连接Broker应该使用failover协议。
  • failover:(tcp://192.168.0.222:51511,tcp://192.168.0.223:51512,tcp://192.168.0.224:51513)?randomize=false

10、集群高可用测试

  • 当一个ActiveMQ节点挂掉,或者一个ZooKeeper节点挂掉,ActiveMQ服务依然正常运转。如果仅剩一个ActiveMQ节点,因为不能选举Master,ActiveMQ不能正常运转;同样的,如果ZooKeeper仅剩一个节点活动,不管ActiveMQ各节点是否存活,ActiveMQ也不能正常提供服务。
  • (ActiveMQ集群的高可用,依赖于ZooKeeper集群的高可用。)

11、设置开机启动:

# vi /etc/rc.local
## activemq
su - hk -c 'cd /home/hk/activemq/node-01/bin/ && ./activemq start'
su - hk -c 'cd /home/hk/activemq/node-02/bin/ && ./activemq start'
su - hk -c 'cd /home/hk/activemq/node-03/bin/ && ./activemq start'

12、配置优化

  • updateURIsURL,通过URL(或者本地路径)获取重连的url,这样做具有良好的扩展性,因为客户端每次连接都是从URL(或文件)中加载一次,所以可以随时从文件中更新url列表,做到动态添加MQ的备点。
  • failover:()?randomize=false&updateURIsURL=file:/home/hk/activemq/urllist.txt
  • urllist.txt中的地址通过英文逗号分隔,示例:
  • tcp://192.168.0.222:51511,tcp://192.168.0.223:51512,tcp://192.168.0.224:51513
  • 最后,附上官方文档的一则警告,请使用者注意。replicatedLevelDB不支持延迟或者计划任务消息。这些消息存储在另外的LevelDB文件中,如果使用延迟或者计划任务消息,将不会复制到slave Broker上,不能实现消息的高可用。

三、负载均衡集群

主要配置【需要自己再手动搭一套集群

  • 本人搭建一套伪集群【ip:192.168.0.225】

集群1链接集群2:

# vi activemq.xml
<broker>
	<networkConnectors>
		<networkConnector uri="static:(tcp://192.168.0.225:53531,tcp://192.168.0.225:53532,tcp://192.168.0.225:53533)" duplex="false"/>
	</networkConnectors>
</broker>

集群2链接集群1:

# vi activemq.xml
<broker>
	<networkConnectors>
		<networkConnector uri="static:(tcp://192.168.0.222:51511,tcp://192.168.0.223:51512,tcp://192.168.0.224:51513)" duplex="false"/>
	</networkConnectors>
</broker>

自行模拟高可用及负载均衡场景测试【点击下载测试代码

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐