activemq消息队列高可用性和负载均衡


activemq5.9后提供了三种集群方式:
1.基于共享文件系统的,默认
  1. <persistenceAdapter>  
  2.     <kahaDB directory="${activemq.data}/kahadb"/>  
  3. </persistenceAdapter> 
2.基于jdbc的
  1. <bean id="mysql-ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
  2.     <property name="driverClassName" value="com.mysql.jdbc.Driver"/>  
  3.     <property name="url" value="jdbc:mysql://localhost:3306/amq?relaxAutoCommit=true"/>  
  4.     <property name="username" value="root"/>  
  5.     <property name="password" value="root"/>  
  6.     <property name="maxActive" value="20"/>  
  7.     <property name="poolPreparedStatements" value="true"/>  
  8. </bean>  
  9. <persistenceAdapter>  
  10.     <jdbcPersistenceAdapter dataDirectory="${activemq.data}" dataSource="#mysql-ds" createTablesOnStartup="false"/>  
  11. </persistenceAdapter>  
3.我们选用第三种方式,可复制的leveldb,是单进程的服务,处理数据量大,占用内存小,是三种中比较优越的
  1. <persistenceAdapter>  
  2.     <replicatedLevelDB  
  3.         directory="${activemq.data}/leveldb"  
  4.         replicas="3"  //集群中节点个数
  5.         bind="tcp://0.0.0.0:62621" //集群通信端口,不是消息端口,也不是mq管控台端口,可以理解为mq集群和zookeeper通信端口  
  6.         zkAddress="localhost:2182,localhost:2183,localhost:2184"  //zookeeper集群地址
  7.         hostname="edu-zk-01"  //绑定的主机名,需要到hosts配置文件绑定域名
  8.         zkPath="/activemq/leveldb-stores"  
  9.     />  
  10. </persistenceAdapter>  

下面说一下集群的端口号:
有3台mq实例,部署在一台机器上
节点一消息通信端口:51515,管控台端口8151,和zk通信端口62621,就是上面的bind中的端口号
节点二消息通信:51516 ,管控台:8162,zk通信62622
节点三消息通信:51517 管控台:8163,zk通信62623
有3台zookeeper实例,也部署在一台机器上,
节点一端口是:2182,节点二端口2183,节点32184

一:首先搭建zookeeper集群
1.解压zookeeper-3.4.6.tar.gz安装包,重命名为node1
解压zookeeper-3.4.6.tar.gz安装包,重命名为node2
解压zookeeper-3.4.6.tar.gz安装包,重命名为node3
2.分别进入node1,node2,node3 下的conf 目录,cp zoo_sample.cfg zoo.cfg
3.编辑node1下的zoo.cfg文件:
tickTime=2000 #心跳检测时间间隔,2s
initLimit=10 #超过10个心跳时间间隔还没有收到客户端的返回信息就提示客户端连接失败
syncLimit=5 #主节点和从节点发送消息,最长不能超过5个心跳间隔
clientPort=2182 #端口号分别为2182,2183,2184
dataDir=/Users/yp-tc-m-7129/soft/zookeeper/node1/data #保存数据的目录,需要修改
dataLogDir = /Users/yp-tc-m-7129/soft/zookeeper/node1/logs #每个文件需要修改保存日志文件的目录
server.1=127.0.0.1:2889:3889
server.2=127.0.0.1:2890:3890
server.3=127.0.0.1:2891:3891
#serer.a=b:c:d
a是个数字,表示是第几号服务器,b是服务器的ip地址或者已经做了域名映射的主机名(/etc/hosts做的域名映射主机名)
c表示这个服务和集群中的leader交换信息的端口,d表示leader挂掉了专门用来选举leader所用的端口。
4.进入配置的dataDir的路径下创建myid文件,文件名不能变
node1下的dataDir路径下的myid文件内容为1,剩下依次为2,3
4.启动zookeeper
分别进入node1,2,3的bin目录下,./zkServer.sh start 启动
5.输入jps,其中quorumpeermain表示zookeeper进程,有3个说明启动正常
6.在bin目录下输入:./zkServer.sh status 查看zk实例的状态,follower表示从节点,leader表示主节点
至此,zk集群搭建完成

二:搭建mq集群
1.解压apache-activemq-5.11.1-bin.tar.gz,重命名为node1
解压apache-activemq-5.11.1-bin.tar.gz,重命名为node2
解压apache-activemq-5.11.1-bin.tar.gz,重命名为node3
2.修改管控台控制端口,在conf/jetty.xml中
<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>
3.在conf/activemq.xml中配置持久化适配器, 每个mq的brokername必须相同,否则不能加入集群
<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="localhost:2182,localhost:2183,localhost:2184"
zkPath="/activemq/leveldb-stores" />
</persistenceAdapter>
</broker>
4.修改各节点的消息端口,都要修改
<transportConnector name="openwire" uri="tcp://0.0.0.0:51515? maximumConnections=1000&wireformat.maxFrameSize=104857600"/>
5.按顺序启动并监听日志
进入bin目录下,./activemq start,日志在你配置的dataDir路径下
6.节点状态分析:
使用zookeeper-dev-ZooInspector.jar对急群中的一个节点抓取,根据抓图获取节点的状态变化
这个观察节点是注册在zookeeper中的节点,之前配置的4个节点有1个因为名称不同不是同一个集群中的还是显示在了这里。
至此,集群搭建完毕。
7.如果要实现集群的负载均衡需要两个大集群,集群A,集群B
在ab之间配置网桥,就可以实现客户端A发送给集群A的消息可以被A,B集群同时消费,客户端B发送给集群A的消息可以被A,B集群同时消费,集群A或者集群B中的主从节点的切换,不会影响集群的新能和消息的丢失,甚至整个集群宕机后,还是可以通过另一个集群来实现消息的处理,但是这种方式实用性可能比较浪费资源吧,性能是优越的。
"网桥"的配置是:在conf/activemq.xml中的broker节点中配置
集群 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 链接集群 1:
<networkConnectors>
<networkConnector uri="static:(tcp://192.168.1.81:51511,tcp://192.168.1.82:51512,tcp://192.168.1.83:51513)" duplex="false"/>
</networkConnectors>
8.如果涉及到权限方面,请修改 activemq.xml中的broker节点中添加如下配置
  1. <plugins>  
  2.             <simpleAuthenticationPlugin>  
  3.                 <users>  
  4.                     <authenticationUser username="admin" password="admin" groups="users,admins"/>  
  5.                 </users>  
  6.             </simpleAuthenticationPlugin>  
  7.         </plugins>  

经过测试发现:
集群搭建后,当一个activemq节点挂掉,或者一个zookeeper节点挂掉,activemq服务仍然正常运转
如果2个activemq挂掉,因为不能选举master,所以消息服务停止。
同样的,如果仅剩一个zookeeper节点,不管activemq各个节点是否活跃,都不能提供服务,并且,zk服务恢复后,还需要重启mq中的各个节点,集群才会运转正常。请注意,只有主节点的管控台才可以打开,从节点的管控台是打不开的

集群靠可用原理:
使用zk注册所有的activemq节点,只有其中一个节点可以提供服务,被视为master,其他节点处于待机状态,被视为slave。
slave连接maste并且同步他们的存储状态,slave不接受客户端连接,所有的存储操作都会被复制到连接至master的slaves。
当master宕机了,zk会从slave中选举出一个broker充当主节点,宕机后恢复的主节点会是从节点。

其他部分:删除不活跃队列的几种方式
1.通过修改activemq.xml配置文件,每小时检测一次,发现队列闲置时间唱过几分钟或几小时后删除无效队列
< broker xmlns ="http://activemq.apache.org/schema/core" brokerName ="localhost" dataDirectory ="${activemq.data}" schedulePeriodForDestinationPurge ="3600000"> < destinationPolicy > < policyMap > < policyEntries > < policyEntry topic =">"> < pendingMessageLimitStrategy > < constantPendingMessageLimitStrategy limit ="1000"/> </ pendingMessageLimitStrategy > </ policyEntry > < policyEntry queue =">" gcInactiveDestinations ="true" inactiveTimoutBeforeGC ="30000"/> </ policyEntries > </ policyMap > </ destinationPolicy > </ broker >
schedulePeriodForDestinationPurge表示1小时去检查一次,0表示关闭删除无效队列功能
gcInactiveDestinations 表示是否删除无效队列
inactiveTimoutBeforeGC 表示队列被闲置30秒后删除
2.或者web中手动删除,活跃队列删除不了的

问题:
1.在集群刚搭建起来并且没有消费者的时候,很有可能会有集群主节点切换的闪动,一会节点1一会节点2
有人说这是因为你的leveldb数据不是空的,需要清空里面的数据
2.集群./activemq stop后之前的数据会丢失?
单个节点stop之后再启动数据会丢失,集群环境下启动的时候只要还没有ack确认就不会消息丢失
3.集群主节点宕机后,确实选择了02作为主节点,但是02为啥没有处理消息呢
4.为啥那边的消费节点会是2个呢?
5.为啥在发消息的时候想删除队列发现不可用呢?
集群环境下好像必须要在集群中不是活跃队列甚至没有活跃队列的时候才能删除队列
6.明明zk抓取图显示的选中的节点是04,打开04的管控台也是正常的,但是怎么客户端就是连接不上呢
2017-09-15 17:54:59,068 INFO [MQProducer.java:41] : 即将发送消息{"age":0,"id":"消息0","name":"测试"}
2017-09-15 17:55:04,129 INFO [SingleConnectionFactory.java:311] : Established shared JMS Connection: PooledConnection { ConnectionPool[ActiveMQConnection {id=ID:yp-tc-m-7129deMacBook-Air.local-55471-1505469304013-1:1,clientId=null,started=false}] }
2017-09-15 17:55:09,376 WARN [FailoverTransport.java:1100] : Failed to connect to [tcp://127.0.0.1:51515, tcp://127.0.0.1:51516, tcp://127.0.0.1:51517, tcp:127.0.0.1:51518] after: 10 attempt(s) continuing to retry.
这个原因不知道,所以建议4个节点,当其中主节点坏掉之后,而且很奇怪,zk抓取图显示主节点是它,它的管控台也能正常打开,但是就是说集群连接不上,直接建议停止这个主节点的服务,会自动选举出来新的主节点,恢复集群的服务。


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值