afredlyj / mynote

idea and note
1 stars 0 forks source link

ActiveMQ 使用 #14

Open afredlyj opened 8 years ago

afredlyj commented 8 years ago

ActiveMQ集群

在ActiveMQ 5.9.0之后,支持基于Zookeeper的复制LevelDB搭建主从,提供高可用服务。 5.8.0以前的版本,支持三种Master-Slave,5.9.0之后,Pure Master-Slave机制被废弃:

  1. 基于共享储存的Master-Slave:多个broker实例使用一个存储文件,谁拿到文件锁就是master,其他处于待启动状态,如果master挂掉了,某个抢到文件锁的slave变成master。由于使用的还是master的存储文件,所以数据好似一致的。
  2. 基于JDBC的Master-Slave:使用同一个数据库,拿到LOCK表的写锁的broker成为master,机制同上。
  3. Pure Master-Slave:Slave的broker,简单的从Master复制数据和状态,问题较多,已被废弃。

这几种方式详情可以参考官网

我尝试使用zk + LevelDB 搭建主从,在搭建过程中遇到一些问题,记录下来。

实现原理

Zookeeper是apache开源的分布式协调服务,ActiveMQ使用Zookeeper进行集群选举,成为master的节点处理客户端的请求,而其他节点进入slave模式,同步master的数据,但是不接受客户端连接,包括console后台。所有的持久化操作都会被同步到slave节点,如果当前master 挂掉,拥有最新数据的slave会晋升为master,然后处理客户端请求,挂掉的节点回复之后,以slave角色加入集群。

从上可知,主从只提供高可用服务,并不能负载均衡。同时,客户端需要failover机制配合。 所有的持久化操作,需要等待集群中大部分节点都更新成功之后,操作才算完成,比如replicas为3,则最少需要2((3/2+1)=2)个节点同步完成(包括master)。此时,master在数据持久化后,会继续等待其中的1个slave更新完成。另外的slave节点通过异步方式复制数据。

搭建细节

  1. 集群节点配置文件中的brokerName属性需要保持一致,否则会被当做不同集群;
  2. bind、hostname和weight参数可以根据实际情况配置,其中bind的端口需要是当前未占用的端口,否则报错;hostname需要配置当前服务器的host或者ip;
  3. 可以在zk的znode中查看集群信息,比如当前的节点数,以及各个节点的角色,zk中的path需要在ActiveMQ的配置文件中指定;
  4. 用apache-activemq-5.10.0搭建集群,总是报错:
java.io.IOException: com.google.common.base.Objects.firstNonNull(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
        at org.apache.activemq.util.IOExceptionSupport.create(IOExceptionSupport.java:39)[activemq-client-5.10.0.jar:5.10.0]
        at org.apache.activemq.leveldb.LevelDBClient.might_fail(LevelDBClient.scala:552)[activemq-leveldb-store-5.10.0.jar:5.10.0]
        at org.apache.activemq.leveldb.LevelDBClient.replay_init(LevelDBClient.scala:657)[activemq-leveldb-store-5.10.0.jar:5.10.0]
        at org.apache.activemq.leveldb.LevelDBClient.start(LevelDBClient.scala:558)[activemq-leveldb-store-5.10.0.jar:5.10.0]
        at org.apache.activemq.leveldb.DBManager.start(DBManager.scala:648)[activemq-leveldb-store-5.10.0.jar:5.10.0]
        at org.apache.activemq.leveldb.LevelDBStore.doStart(LevelDBStore.scala:235)[activemq-leveldb-store-5.10.0.jar:5.10.0]
        at org.apache.activemq.leveldb.replicated.MasterLevelDBStore.doStart(MasterLevelDBStore.scala:110)[activemq-leveldb-store-5.10.0.jar:5.10.0]
        at org.apache.activemq.util.ServiceSupport.start(ServiceSupport.java:55)[activemq-client-5.10.0.jar:5.10.0]
        at org.apache.activemq.leveldb.replicated.ElectingLevelDBStore$$anonfun$start_master$1.apply$mcV$sp(ElectingLevelDBStore.scala:226)[activemq-leveldb-store-5.10.0.jar:5.10.0]
        at org.fusesource.hawtdispatch.package$$anon$4.run(hawtdispatch.scala:330)[hawtdispatch-scala-2.11-1.21.jar:1.21]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)[:1.7.0_40]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)[:1.7.0_40]
        at java.lang.Thread.run(Thread.java:724)[:1.7.0_40]
 INFO | Stopped LevelDB[/usr/local/activemq-61617/data/LevelDB]

解决办法: a. 修改activemq.xml,注释掉节点logQuery;

  <!-- Allows accessing the server log 
    <bean id="logQuery" class="org.fusesource.insight.log.log4j.Log4jLogQuery"
          lazy-init="false" scope="singleton"
          init-method="start" destroy-method="stop">
    </bean>
   -->

b. 删除lib目录下的pax-url-aether-1.5.2.jar

参考文档

  1. http://blog.csdn.net/kimmking/article/details/13768367
  2. http://blog.csdn.net/kimmking/article/details/8440150