本帖最后由 逆风TO 于 2018-4-6 10:42 编辑
1 ActiveMQ集群的由来单点的ActiveMQ作为企业应用无法满足业务的需求,因为单点的ActiveMQ存在单点故障问题,当该节点宕机以后,就会直接影响我们业务的正常运转,所以我们需要搭建高可用的ActiveMQ集群来支撑我们的业务系统 2 ActiveMQ集群的主要部署方式2.1 默认的单机部署(kahadb)activeMQ的默认存储的单机方式,以本地kahadb文件的方式存储,所以性能指标完全依赖本地磁盘IO,不能提供高可用。 <persistenceAdapter>
<kahaDB directory="${activemq.data}/kahadb"/> </persistenceAdapter> 2.2 基于共享数据库的主从(Shared JDBC Master/Slave)可以基于postgres、mysql、oracle等常用数据库。每个节点启动都会争抢数据库锁,从而保证master的唯一性,其他节点作为备份,一直等待数据库锁的释放。因为所有消息读写,其实都是数据库操作,activeMQ节点本身压力很小,性能完全取决于数据库性能。优点:实现高可用和数据安全,简单灵活,2台节点就可以实现高可用. 缺点:稳定性依赖数据库,性能依赖数据库. <beanid="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> 2.3 基于zookeeper以及可复制的 LevelDB实现5.9.0新推出的主从实现,基于zookeeper来选举出一个master,其他节点自动作为slave实时同步消息。因为有实时同步数据的slave的存在,master不用担心数据丢失,所以leveldb会优先采用内存存储消息,异步同步到磁盘。所以该方式的activeMQ读写性能都最好,特别是写性能能够媲美非持久化消息。优点:实现高可用和数据安全性能较好.缺点:因为选举机制要超过半数,所以最少需要3台节点,才能实现高可用。
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> 了解完毕ActiveMQ集群的三种部署方式以后,我们本教程将采用第三种方式来建ActiveMQ集群,因为第三种的读写性能都最好的. 3 ActiveMQ高可用原理使用ZooKeeper(集群)注册所有的ActiveMQ Broker。只有其中的一个Broker可以提供服务,被视为 Master,其他的 Broker 处于待机状态,被视为Slave。如果Master因故障而不能提供服务,Zookeeper会从Slave中选举出一个Broker充当Master。Slave连接Master并同步他们的存储状态,Slave不接受客户端连接。所有的存储操作都将被复制到 连接至 Master的Slaves。如果Master宕了,得到了最新更新的Slave会成为 Master。故障节点在恢复后会重新加入到集群中并连接Master进入Slave模式。 1 基于zookeeper以及leveldb实现高可用ActiveMQ集群了解完毕ActiveMQ集群的三种部署方式以后,我们本教程将采用第三种方式来建ActiveMQ集群,因为第三种的读写性能都最好的. 1.1 ActiveMQ集群部署规划环境: CentOS 6.6 x64 、 JDK7
版本: ActiveMQ 5.11.1 zookeeper集群说明: 192.168.221.141:2181 , 192.168.221.141:2182, 192.168.221.141:2183 集群节点规划说明: 主机 | | | | | | | | | | | /usr/local/src/activemq-cluster | | | | | | | | | | | 1.2 搭建ActiveMQ步骤1.2.1 准备环境Ø 在/usr/local/src/在创建activemq-cluster目录: mkdir –p /usr/local/src/activemq-cluster Ø 上传activemq安装包到linux服务器下 Ø 解压activemq的安装包: tar –zxvf –C /usr/local/src/activemq-cluster Ø 重命名: mv apache-activemq-5.12.0/ activemq-cluster-node01 Ø 以1节点为基础复制两个节点出来 ² cp –r activemq-cluster-node01 activemq-cluster-node02 ² cp –r activemq-cluster-node01 activemq-cluster-node03 1.2.2 修改管理控制台端口可在 conf/jetty.xml 中修改node01管控台端口 <bean id="jettyPort" class="org.apache.activemq.web.WebConsolePort" init-method="start"> <property name="host" value="0.0.0.0"/> <property name="port" value="8161"/> </bean> |
node02管控台端口 <bean id="jettyPort" class="org.apache.activemq.web.WebConsolePort" init-method="start"> <property name="host" value="0.0.0.0"/> <property name="port" value="8162"/> </bean> |
node03管控台端口 <bean id="jettyPort" class="org.apache.activemq.web.WebConsolePort" init-method="start"> <property name="host" value="0.0.0.0"/> <property name="port" value="8163"/> </bean> | 1.2.3 配置持久化适配器在 3 个 ActiveMQ 节点中配置 conf/activemq.xml 中的持久化适配器。修改其中 bind、zkAddress、hostname 和 zkPath.注意:每个 ActiveMQ 的 BrokerName 必须相同,否则不能加入集群。 node01-持久化适配器: <broker xmlns="http://activemq.apache.org/schema/core" brokerName="activemq-cluster" dataDirectory="${activemq.data}"> <persistenceAdapter> <replicatedLevelDB directory="${activemq.data}/leveldb" replicas="3" bind="tcp://192.168.221.136:62621" zkAddress="192.168.80.129:2182,192.168.80.129:2183,192.168.80.129:2184" hostname="192.168.80.129" zkPath="/activemq/leveldb-stores" /> </persistenceAdapter> </broker> |
node02-持久化适配器: <broker xmlns="http://activemq.apache.org/schema/core" brokerName="activemq-cluster" dataDirectory="${activemq.data}"> <persistenceAdapter> <replicatedLevelDB directory="${activemq.data}/leveldb" replicas="3" bind="tcp://192.168.221.136:62622" zkAddress="192.168.221.145:2181,192.168.221.145:2182,192.168.221.145:2183" hostname="192.168.221.136" zkPath="/activemq/leveldb-stores" /> </persistenceAdapter> </broker> |
node03-持久化适配器: <broker xmlns="http://activemq.apache.org/schema/core" brokerName="activemq-cluster" dataDirectory="${activemq.data}"> <persistenceAdapter> <replicatedLevelDB directory="${activemq.data}/leveldb" replicas="3" bind="tcp://192.168.221.136:62623" zkAddress="192.168.221.145:2181,192.168.221.145:2182,192.168.221.145:2183" hostname="192.168.221.136" zkPath="/activemq/leveldb-stores" /> </persistenceAdapter> </broker> | 1.2.4 修改消息服务端口node-01消息服务端口: <transportConnectors> <transportConnector name="openwire" uri="tcp://0.0.0.0:11616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> <transportConnector name="amqp" uri="amqp://0.0.0.0:1672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> <transportConnector name="stomp" uri="stomp://0.0.0.0:11613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> <transportConnector name="ws" uri="ws://0.0.0.0:11614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> </transportConnectors> |
node-02消息服务端口: <transportConnectors> <transportConnector name="openwire" uri="tcp://0.0.0.0:21616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> <transportConnector name="amqp" uri="amqp://0.0.0.0:2672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> <transportConnector name="stomp" uri="stomp://0.0.0.0:21613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> <transportConnector name="mqtt" uri="mqtt://0.0.0.0:2883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> <transportConnector name="ws" uri="ws://0.0.0.0:21614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> </transportConnectors> |
node-03消息服务端口: <transportConnectors> <transportConnector name="openwire" uri="tcp://0.0.0.0:31616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> <transportConnector name="amqp" uri="amqp://0.0.0.0:3672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> <transportConnector name="stomp" uri="stomp://0.0.0.0:31613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> <transportConnector name="mqtt" uri="mqtt://0.0.0.0:3883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> <transportConnector name="ws" uri="ws://0.0.0.0:31614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> </transportConnectors> | 1.2.5 启动3个ActiveMQ集群节点 /usr/local/src/activemq-cluster/apache-activemq-01/bin/activemq start /usr/local/src/activemq-cluster/apache-activemq-02/bin/activemq start /usr/local/src/activemq-cluster/apache-activemq-03/bin/activemq start 监听日志 tail -f /usr/local/src/activemq-cluster/apache-activemq-01/data/activemq.log tail -f /usr/local/src/activemq-cluster/apache-activemq-02/data/activemq.log tail -f /usr/local/src/activemq-cluster/apache-activemq-03/data/activemq.log | 1.2.6 集群的节点状态分析
使用集群启动后对 ZooKeeper 数据的抓图,可以看到 ActiveMQ 的有 3 个节点,分别是 00000000019,000000000020, 00000000021。以下第一张图展现了 00000000019 的值,可以看到 elected 的值是不为空,说明这个节点是 Master,其他两个节点是 Slave。 1.1.1 集群测试ActiveMQ的客户端只能访问MasterBroker,其他处于Slave的Broker不能访问.所以客户端连接Broker应该使用failover(故障转移)协议 failover:(tcp://192.168.221.136:11616,tcp://192.168.221.136:21616,tcp:// 192.168.221.136:31616)?randomize=false 1.1.2 客户端连接url配置优化updateURIsURL,通过 URL(或者本地路径)获取重连的 url,这样做具有良好的扩展性,因为客户端每次连接都是从 URL(或文件)中加载一次,所以可以随时从文件中更新 url 列表,做到动态添加 MQ 的备点。failover:()?randomize=false&updateURIsURL=file:/home/wusc/activemq/urllist.txt,urllist.txt 中的地址通过英文逗号分隔,示例: tcp://192.168.221.136:11616,tcp://192.168.221.136:21616,tcp:// 192.168.221.136:31616 1.1.3 集群测试结果说明
当一个ActiveMQ节点挂掉,或者一个ZooKeeper节点挂掉,ActiveMQ服务依然正常运转.如果仅剩一个ActiveMQ节点,因为不能选举Master,ActiveMQ不能正常运转;同样的,如果ZooKeeper仅剩一个节点活动.不管ActiveMQ 各节点是否存活,ActiveMQ也不能正常提供服务。(ActiveMQ 集群的高可用,依赖于 ZooKeeper 集群的高可用)。
|