从 ActiveMQ 5.9 开始,ActiveMQ 的集群实现方式取消了传统的 Master-Slave 方式,增加了基于 ZooKeeper + LevelDB 的 Master-Slave 实现方式, 本次介绍的集群仅提供主备方式的高可用集群功能,避免单点故障,没有负载均衡功能。
官方文档: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 失败了,服务中断。
规划
- 环境:CentOS 6.5 x64、JDK7
- 版本:ActiveMQ 5.9
- ZooKeeper 集群环境
172.16.129.18:2181
172.16.129.21:2181
172.16.129.22:2181
主机 | 集群端口 | 消息端口 | 管控台端口 | 节点安装目录 |
---|---|---|---|---|
172.16.129.18 | 62621 | 61616 | 8161 | /user/local/acvivemq |
172.16.129.21 | 62621 | 61616 | 8161 | /user/local/acvivemq |
172.16.129.22 | 62621 | 61616 | 8161 | /user/local/acvivemq |
集群配置
在 3 个 ActiveMQ 节点配置 conf/activemq.xml
持久化适配器,修改其中 bind
、zkAddress
、hostname
和 zkPath
。
修改 brokerName
为 platform_app
(可改可不改)
注意:每个 activemq 的 BrokerName 必须相同,否则不能加入集群。
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}">
<destinationPolicy>
.....
</destinationPolicy>
....
<persistenceAdapter>
...
</persistenceAdapter>
</broker>
最为重要的是修改 persistenceAdapter
部分,将其默认的注释,加入如下:
<!-- node1 -->
<replicatedLevelDB
directory="${activemq.data}/leveldb"
replicas="3"
bind="tcp://0.0.0.0:62621"
zkAddress="172.16.129.18:2181,172.16.129.21:2181,172.16.129.22:2181"
hostname="redis18" zkPath="/activemq/leveldb-stores"
/>
<!-- node2 -->
<replicatedLevelDB
directory="${activemq.data}/leveldb"
replicas="3"
bind="tcp://0.0.0.0:62621"
zkAddress="172.16.129.18:2181,172.16.129.21:2181,172.16.129.22:2181"
hostname="redis21" zkPath="/activemq/leveldb-stores"
/>
<!-- node3 -->
<replicatedLevelDB
directory="${activemq.data}/leveldb"
replicas="3"
bind="tcp://0.0.0.0:62621"
zkAddress="172.16.129.18:2181,172.16.129.21:2181,172.16.129.22:2181"
hostname="redis22" zkPath="/activemq/leveldb-stores"
/>
其它配置
- 修改
jmx.password
# admin activemq
jiangyong jiangyongpwd
- 修改
credentials.properties
#activemq.username=system
#activemq.password=manager
#guest.password=password
activemq.username=jiangyong
activemq.password=jiangyongpwd
guest.password=password
- 修改
jetty-realm.properties
#admin: admin, admin
#user: user, user
admin: jiangyongpwd, admin
创建启动脚本
$ ln -s /usr/local/activemq/bin/activemq /etc/init.d/activemq
启动服务并监听日志
需先启动 zookeeper 集群服务
$ service activemq start
$ tail -f /usr/local/activemq/data/activemq.log
输出如下 INFO 信息则表示配置成功
[root@redis18 data]# tail -f activemq.log
2017-11-10 18:34:44,631 | WARN | SASL configuration failed: javax.security.auth.login.LoginException: No JAAS configuration section named 'Client' was found in specified JAAS configuration file: '/usr/local/activemq//conf/login.config'. Will continue connection to Zookeeper server without SASL authentication, if Zookeeper server allows it. | org.apache.zookeeper.ClientCnxn | main-SendThread(172.16.129.21:2181)
2017-11-10 18:34:44,634 | INFO | Opening socket connection to server 172.16.129.21/172.16.129.21:2181 | org.apache.zookeeper.ClientCnxn | main-SendThread(172.16.129.21:2181)
2017-11-10 18:34:44,634 | WARN | unprocessed event state: AuthFailed | org.apache.activemq.leveldb.replicated.groups.ZKClient | main-EventThread
2017-11-10 18:34:44,643 | INFO | Socket connection established to 172.16.129.21/172.16.129.21:2181, initiating session | org.apache.zookeeper.ClientCnxn | main-SendThread(172.16.129.21:2181)
2017-11-10 18:34:44,660 | INFO | Session establishment complete on server 172.16.129.21/172.16.129.21:2181, sessionid = 0x1504475b64c90001, negotiated timeout = 4000 | org.apache.zookeeper.ClientCnxn | main-SendThread(172.16.129.21:2181)
2017-11-10 18:34:44,963 | INFO | Using the pure java LevelDB implementation. | org.apache.activemq.leveldb.LevelDBClient | ActiveMQ BrokerService[localhost] Task-1
2017-11-10 18:34:44,975 | INFO | Attaching to master: tcp://redis21:62621 | org.apache.activemq.leveldb.replicated.SlaveLevelDBStore | ActiveMQ BrokerService[localhost] Task-1
2017-11-10 18:34:44,984 | INFO | Slave started | org.apache.activemq.leveldb.replicated.MasterElector | ActiveMQ BrokerService[localhost] Task-1
2017-11-10 18:34:45,210 | INFO | Attaching... Downloaded 0.00/0.00 kb and 1/1 files | org.apache.activemq.leveldb.replicated.SlaveLevelDBStore | hawtdispatch-DEFAULT-3
2017-11-10 18:34:45,212 | INFO | Attached | org.apache.activemq.leveldb.replicated.SlaveLevelDBStore | hawtdispatch-DEFAULT-3
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于