JMS之——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>
二、原理
官方文档: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.5 x64 、 JDK7
版本: ActiveMQ 5.14.4
ZooKeeper 集群环境: 192.168.50.132:2181,192.168.50.133:2182,192.168.50.134:2183
(ZooKeeper 集群部署请参考《Dubbo之——Dubbo 注册中心集群Zookeeper-3.4.9的安装、 配置 》)
| 主机 | 集群端口 | 消息端口 | 控制台端口 | 节点安装目录 |
| 192.168.50.132 | 62621 | 51511 | 8161 | /usr/local/activemq/node-01 |
| 192.168.50.133 | 62622 | 51512 | 8162 | /usr/local/activemq/node-02 |
| 192.168.50.134 | 62623 | 51513 | 8163 | /usr/local/activemq/node-03 |
2、 防火墙打开对应的端口
- ## mq cluster
- ## 192.168.50.132
- -A INPUT -m state --state NEW -m tcp -p tcp --dport 8361 -j ACCEPT
- -A INPUT -m state --state NEW -m tcp -p tcp --dport 53531 -j ACCEPT
- -A INPUT -m state --state NEW -m tcp -p tcp --dport 63631 -j ACCEPT
- ## 192.168.50.133
- -A INPUT -m state --state NEW -m tcp -p tcp --dport 8362 -j ACCEPT
- -A INPUT -m state --state NEW -m tcp -p tcp --dport 53532 -j ACCEPT
- -A INPUT -m state --state NEW -m tcp -p tcp --dport 63632 -j ACCEPT
- ## 192.168.50.134
- -A INPUT -m state --state NEW -m tcp -p tcp --dport 8363 -j ACCEPT
- -A INPUT -m state --state NEW -m tcp -p tcp --dport 53533 -j ACCEPT
- -A INPUT -m state --state NEW -m tcp -p tcp --dport 63633 -j ACCEPT
3、 创建/usr/local/activemq 目录
分别在三台主机中创建/usr/local/activemq 目录
- $ mkdir /usr/local/activemq
上传 apache-activemq-5.14.4-bin.tar.gz 到/usr/local/activemq 目录
4、 解压并按节点命名
- $ cd /usr/local/activemq
- $ tar -xvf apache-activemq-5.14.4-bin.tar.gz
- $ mv apache-activemq-5.14.4 node-0X #(X 代表节点号 1、 2、 3, 下同)
5、修改conf/jetty.xml
修改管理控制台端口(默认为 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="liuyazhuang" 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.50.132:2181,192.168.50.133:2182,192.168.50.134:2183"
- hostname="liuyazhuang132"
- zkPath="/activemq/leveldb-stores"
- />
- </persistenceAdapter>
- </broker>
Node-02 中的持久化配置:
- <broker xmlns="http://activemq.apache.org/schema/core" brokerName="liuyazhuang" 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.50.132:2181,192.168.50.133:2182,192.168.50.134:2183"
- hostname="liuyazhuang133"
- zkPath="/activemq/leveldb-stores"
- />
- </persistenceAdapter>
- </broker>
Node-03 中的持久化配置:
- <broker xmlns="http://activemq.apache.org/schema/core" brokerName="liuyazhuang" 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.50.132:2181,192.168.50.133:2182,192.168.50.134:2183"
- hostname="liuyazhuang134"
- zkPath="/activemq/leveldb-stores"
- />
- </persistenceAdapter>
- </broker>
修改各节点的消息端口(注意,避免端口冲突):
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&wireFormat.maxFrameSize=104857600"/>
- <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
- <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?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:61614?maximumConnections=1000&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&wireFormat.maxFrameSize=104857600"/>
- <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
- <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?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:61614?maximumConnections=1000&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&wireFormat.maxFrameSize=104857600"/>
- <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
- <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?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:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
- </transportConnectors>
7、 启动ActiveMQ并监听日志
按顺序启动 3 个 ActiveMQ 节点
- $ /usr/local/activemq/node-01/bin/activemq start
- $ /usr/local/activemq/node-02/bin/activemq start
- $ /usr/local/activemq/node-03/bin/activemq start
监听日志:
- $ tail -f /usr/local/activemq/node-01/data/activemq.log
- $ tail -f /usr/local/activemq/node-02/data/activemq.log
- $ tail -f /usr/local/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.50.132:51511,tcp://192.168.50.133:51512,tcp://192.168.50.134:51513)?randomize=false
10、 集群高可用测试
当一个 ActiveMQ 节点挂掉,或者一个 ZooKeeper 节点挂掉, ActiveMQ 服务依然正常运转。如果仅剩一个 ActiveMQ 节点,因为不能选举 Master, ActiveMQ 不能正常运转; 同样的,如果 ZooKeeper 仅剩一个节点活动,不管 ActiveMQ 各节点是否存活, ActiveMQ 也不能正常提供服务。(ActiveMQ 集群的高可用,依赖于 ZooKeeper 集群的高可用。)
11、 设置开机启动
- # vi /etc/rc.local
- /usr/local/activemq/node-01/bin/activemq start
- /usr/local/activemq/node-02/bin/activemq start
- /usr/local/activemq/node-03/bin/activemq start
12、 配置优化
updateURIsURL,通过 URL(或者本地路径)获取重连的 url,这样做具有良好的扩展性,因为客户端每次连接都是从 URL(或文件)中加载一次,所以可以随时从文件中更新 url 列表,做到动态添加 MQ 的备点。failover:()?randomize=false&updateURIsURL=file:/home/wusc/activemq/urllist.txt
urllist.txt 中的地址通过英文逗号分隔,示例:
- tcp://192.168.50.132:51511,tcp://192.168.50.133:51512,tcp://192.168.50.134:51513
13、官方文档的一则警告
附上官方文档的一则警告,请使用者注意。 replicatedLevelDB 不支持延迟或者计划任务消息。这些消息存储在另外的 LevelDB 文件中,如果使用延迟或者计划任务消息,将不会复制到 slave Broker 上,不能实现消息的高可用。
四、高可用+负载均衡实现
Broker-Cluster 可以解实现载均衡,但当其中一个 Broker 突然宕掉的话,那么存在于该 Broker 上处于 Pending 状态的 message 将会丢失,无法达到高可用的目的。Master-Slave 与 Broker-Cluster 相结合的部署
1、集群 1 链接集群 2
- <networkConnectors>
- <networkConnector uri="static:(tcp://192.168.1.101:53531,tcp://192.168.1.101:53532,tcp://192.168.1.101:53533)" duplex="false"/>
- </networkConnectors>
2、集群 2 链接集群 1
- <networkConnectors>
- <networkConnector uri="static:(tcp://192.168.50.132:51511,tcp://192.168.50.133:51512,tcp://192.168.50.134:51513)" duplex="false"/>
- </networkConnectors>
注:以上配置需配置到activemq.xml文件中 <persistenceAdapter>... </persistenceAdapter>节点上面,与其为同级节点,具体如下图:

JMS之——ActiveMQ 高可用与负载均衡集群安装、配置(ZooKeeper + LevelDB + Static discovery)的更多相关文章
- 通过LVS+Keepalived搭建高可用的负载均衡集群系统
1. 安装LVS软件 (1)安装前准备操作系统:统一采用Centos6.5版本,地址规划如下: 服务器名 IP地址 网关 虚拟设备名 虚拟ip Director Server 192.168 ...
- haproxy + keepalived + mycat 高可用与负载均衡集群配置 centos7
架构如上,但是其实keepalived.haproxy.Mycat都可以多台(比如keepalived.haproxy.Mycat各3台,3台keepalived抢占vip,然后抢到vip的hapro ...
- haproxy高可用、负载均衡集群
HAProxy提供高可用性.负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费.快速并且可靠的一种解决方案.根据官方数据,其最高极限支持10G的并发.另外其支持从4层至7层的网络交换, ...
- LVS+Keepalived搭建MyCAT高可用負載均衡集群
1.前面我们已经搭建好mysql主主,并且用mycat实现双写功能,主要配置文件: [root@mycat2 conf]# cat schema.xml <?xml version=" ...
- 高性能Linux服务器 第11章 构建高可用的LVS负载均衡集群
高性能Linux服务器 第11章 构建高可用的LVS负载均衡集群 libnet软件包<-依赖-heartbeat(包含ldirectord插件(需要perl-MailTools的rpm包)) l ...
- Haproxy+Keepalived搭建Weblogic高可用负载均衡集群
配置环境说明: KVM虚拟机配置 用途 数量 IP地址 机器名 虚拟IP地址 硬件 内存3G 系统盘20G cpu 4核 Haproxy keepalived 2台 192.168.1.10 192 ...
- nginx集群:nginx配置负载均衡集群(nginx1.18.0)
一,nginx的负载均衡集群的特点: 1,nginx集群和lvs的不同? lvs集群:工作在第4层(传输层) nginx集群:工作在第7层(应用层) lvs集群:性能更强 nginx集群:功能更强:可 ...
- JMS之——ActiveMQ高可用+负载均衡集群
一.高可用集群 从ActiveMQ5.9开始,ActiveMQ的集群实现方式取消了传统的Master-Slave方式,增加了基于ZooKeeper+LevelDB的Master-Slave实现方式,其 ...
- Dubbo入门到精通学习笔记(十四):ActiveMQ集群的安装、配置、高可用测试,ActiveMQ高可用+负载均衡集群的安装、配置、高可用测试
文章目录 ActiveMQ 高可用集群安装.配置.高可用测试( ZooKeeper + LevelDB) ActiveMQ高可用+负载均衡集群的安装.配置.高可用测试 准备 正式开始 ActiveMQ ...
随机推荐
- hdu5728
详细题解: http://blog.csdn.net/wust_zzwh/article/details/51966450 ……化简公式的能力还不够啊…… #include<bits/stdc+ ...
- bzoj 1443 二分图博弈
这种两个人轮流走,不能走 走过的格子的大都是二分图博弈... #include<bits/stdc++.h> #define LL long long #define fi first # ...
- 阿里云Maven仓库配置,Maven镜像配置
Jenkins通过maven对java代码打包编译时,速度太慢,所以修改为阿里的Maven仓库 修改如下: [root@7mini-node2 conf]# vim /software/apache- ...
- 洛谷P3805 [模板]Manacher算法 [manacher]
题目传送门 题目描述 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 字符串长度为n 输入输出格式 输入格式: 一行小写英文字符a,b,c...y,z组成的字符 ...
- 使用CSS让元素尺寸缩小时保持宽高比例一致
CSS中有一个属性padding对元素宽度存在依存关系.如果一个元素的 padding属性以百分比形式表示,padding 的大小是以该元素自身宽度为参照的. 若想要元素尺寸变化时,宽高比例不变,可以 ...
- python脚本实现ipv6的ddns功能
话说在国家的推动下,ipv6地址已经开始优先在三大运营商推广,我自己家用的就是联通宽带100M光纤入户.有一次,不经意间发现,我们的光猫竟然获取到了ipv6地址,于是我开始浮想联翩. 说干就干,我先是 ...
- 洛谷—— P1908 逆序对
https://www.luogu.org/problem/show?pid=1908 题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏, ...
- Spring的远程调用
Spring远程支持是由普通(Spring)POJO实现的,这使得开发具有远程访问功能的服务变得相当容易 四种远程调用技术: ◆ 远程方法调用(RMI) ◆ Caucho的Hessian和Burlap ...
- luogu P1396 营救
题目描述 “咚咚咚……”“查水表!”原来是查水表来了,现在哪里找这么热心上门的查表员啊!小明感动的热泪盈眶,开起了门…… 妈妈下班回家,街坊邻居说小明被一群陌生人强行押上了警车!妈妈丰富的经验告诉她小 ...
- 【动态规划+二分查找】POJ2533&POJ1631最长上升子序列(LIS)
POJ2533裸的LIS,时间复杂度为O(n^2) #include<iostream> #include<cstdio> using namespace std; +; in ...