官方资料:http://activemq.apache.org/clustering.html
ActiveMQ 具有强大和灵活的集群功能,但在使用的过程中会发现很多的缺点, ActiveMQ 的集群方式主要由两种: Master-Slave 和 Broker Cluster 。
1、Master-Slave
Master-Slave方式中,只能是Master提供服务,Slave是实时地备份Master的数据,以保证消息的可靠性。当Master失效时,Slave会自动升级为Master,客户端会自动连接到Slave上工作。Master-Slave模式分为三类:Pure Master Slave、Shared File System Master Slave和JDBC Master Slave。
(1)Pure Master Slave
官方地址:http://activemq.apache.org/pure-master-slave.html
需要两个Broker,一个作为Master,另一个作为Slave,运行时,Slave通过网络实时从Master处复制数据,同时,如果Slave和Master失去连接,Slave就会自动升级为Master,继续为客户端提供消息服务,如图所示:
实践时,我们使用两个ActiveMQ服务器,一个作为Master,Master不需要做特殊的配置;另一个作为Slave,配置${ACTIVEMQ_HOME}/conf/activemq.xml文件,在节点中添加连接到Master的URI和设置Master失效后不关闭Slave,如下:
- <broker xmlns="http://activemq.apache.org/schema/core" brokerName="pure_slave" masterConnectorURI="tcp://0.0.0.0:61616" shutdownOnMasterFailure="false" dataDirectory="${activemq.base}">
同时修改Slave的服务端口,如:
- <transportConnectors>
- <transportConnector name="openwire" uri="tcp://0.0.0.0:61617"/>
- transportConnectors>
为了看到实践的效果,Master和Slave的消息持久化介质都是采用MySQL,并且Master和Slave分别连接不同的数据库。
在消息生产者应用和消息消费者应用的Spring配置文件中添加以下红色内容:
- <property name="brokerURL" value="failover:(tcp://localhost:61616,tcp://localhost:61617)?initialReconnectDelay=100" />
A、启动Master和Slave,启动消息生产者应用,并分别发送一些Queue消息和Topic消息,如果此时订阅Topic消息的消费者设置了clientID,我们就可以在Master的数据库和Slave的数据库中看到尚未消费的消息,包括Queue和Topic的消息;
B、启动消费者应用,可以接收到消息;
C、关闭消费者,生产者继续发送一些消息A;
D、停止Master;
E、生产者继续发送消息B;
F、启动消费者应用,消费者可以接收到消息A和消息B,说明Slave接替了Master的工作并复制了Master的消息。
这种方式只能两台机器做集群,可以起到很好的双机热备功能,但只能失效一次,只能通过停机恢复Master-Slave结构。该模式实际应用场景并不广泛。
(2)Shared File System Master Slave
官方地址:http://activemq.apache.org/masterslave.html
Shared File System Master Slave就是利用共享文件系统做ActiveMQ集群,是基于ActiveMQ的默认数据库kahaDB完成的,kahaDB的底层是文件系统。这种方式的集群,Slave的个数没有限制,哪个ActiveMQ实例先获取共享文件的锁,那个实例就是Master,其它的ActiveMQ实例就是Slave,当当前的Master失效,其它的Slave就会去竞争共享文件锁,谁竞争到了谁就是Master。这种模式的好处就是当Master失效时不用手动去配置,只要有足够多的Slave。Shared File System Master Slave模式如图所示:
本例子是在一台机器上运行三个ActiveMQ实例,需要对ActiveMQ的配置文件做一些简单的配置,就是把持久化适配器的存储目录改为本地磁盘的一个固定目录,三个实例共享这个目录,如下:
- <span style="color: #ff0000;"><persistenceAdapter>
- <kahaDB directory="E:/XXX/XXX/XXX/cluster/shared_file/data/kahadb" />
- persistenceAdapter>span>
然后修改ActiveMQ实例的服务端口和jetty的服务端口,防止端口占用异常。启动三个ActiveMQ实例,就可以进行测试了。
“Apache ActiveMQ单点基本配置” 原配置内容:
- <persistenceAdapter>
- <kahaDB directory="${activemq.data}/kahadb"
- enableIndexWriteAsync="true"
- enableJournalDiskSyncs="false"/>
- <!-- -->
- persistenceAdapter>
- <persistenceAdapter>
- <kahaDB directory="X:\\shareBrokerData"
- enableIndexWriteAsync="true"
- enableJournalDiskSyncs="false"/>
- persistenceAdapter>
1、前面提到部署一台设备上的ActiveMQ系统,需要修改对应的端口号,如ActiveMQ对外的监听端口61616和jetty的监听端口8161等。
2、如果多套ActiveMQ部署在不同的设备上,这里的directory应该指向一个远程的系统目录(分布式文件系统)
Producer for java:
- ActiveMQConnectionFactory connectionFactory =
- new ActiveMQConnectionFactory("failover:(
- tcp://192.168.0.87:61616?wireFormat.maxInactivityDuration=0,
- tcp://192.168.0.87:61617?wireFormat.maxInactivityDuration=0)");
- Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
- Queue queue = session.createQueue(qName);
- ActiveMQMessageProducer producer = (ActiveMQMessageProducer) session.createProducer(queue); // Default DeliveryMode.PERSISTENT
- //producer.setPriority(3); // Default priority 4.
- //producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
- session.createObjectMessage();
- jmsMessage.setObject(message);
- while(true){
- producer.send(jmsMessage);
- TimeUnit.MILLISECONDS.sleep(10);
- }
Consumer for java:
- final String qName = "Test.foo?consumer.prefetchSize=100";
- ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("
- failover:(
- tcp://192.168.0.87:61616,
- tcp://192.168.0.87:61617
- )");
- Connection connection = connectionFactory.createConnection();
- connection.start();
- final Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
- Destination destination = session.createQueue(qName);
- ActiveMQMessageConsumer consumer = (ActiveMQMessageConsumer) session.createConsumer(destination);
- System.out.println(consumer.getPrefetchNumber());
- //listener 方式
- consumer.setMessageListener(new MessageListener() {
- public void onMessage(Message msg) {
- //TODO something....
- try {
- System.out.println("收到消息:"+counter.incrementAndGet()+","+msg);
- } catch (JMSException e1) {
- // TODO Auto-generated
- catch blocke1.printStackTrace();
- }
- }
- });
通过failover方式进行连接,多个ActiveMQ 实例地址使用英文逗号隔开,当某个实例断开时会自动重连,但如果所有实例都失效,failover默认情况下会无限期的等待下去,不会有任何提示。
failover参数配置参考:
http://activemq.apache.org/failover-transport-reference.html
(3)JDBC Master Slave
官方地址:http://activemq.apache.org/masterslave.html
JDBC Master Slave模式和Shared File Sysytem Master Slave模式的原理是一样的,只是把共享文件系统换成了共享数据库。我们只需在所有的ActiveMQ的主配置文件中(${ACTIVEMQ_HOME}/conf/activemq.xml)添加数据源,所有的数据源都指向同一个数据库,如:
- <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/cluster_jdbc?relaxAutoCommit=true"/>
- <property name="username" value="root"/>
- <property name="password" value="root"/>
- <property name="maxActive" value="200"/>
- <property name="poolPreparedStatements" value="true"/>
- bean>
然后修改持久化适配器。这种方式的集群相对Shared File System Master Slave更加简单,更加容易地进行分布式部署,但是如果数据库失效,那么所有的ActiveMQ实例都将失效,它的性能受限于数据库。
以上三种方式的集群都不支持负载均衡,但可以解决单点故障的问题,以保证消息服务的可靠性。
2、Broker Cluster
Broker Cluster主要是通过network of Brokers在多个ActiveMQ实例之间进行消息的路由。Broker的集群分为Static Discovery和Dynamic Discovery两种。
(1)Static Discovery集群
官方地址:http://activemq.apache.org/static-transport-reference.html
Static Discovery集群就是通过硬编码的方式使用所有已知ActiveMQ实例节点的URI地址。如:消息生产者应用连接一个ActiveMQ实例,我们暂时称为MQ1,所有的消息都由该实例提供;两个消息消费者应用分别连接另外两个ActiveMQ实例,分别为MQ2和MQ3,两个消息消费者需要消费MQ1上的消息,但它们连接的都不是MQ1,可以通过Static Discovery方式把MQ1上的消息路由到MQ2和MQ3,为了保证消费者不因某个节点的失效而导致不能消费消息,在消费者应用中需要配置所有节点的URI。
生产者ActiveMQ实例不需要特殊的配置,所有的消费者ActiveMQ实例需要添加networkConnectors节点,连接到生产者MQ实例,如:
- <span style="color: #ff0000;"><networkConnectors>
- <networkConnector uri="static:failover://(tcp://localhost:61616)" duplex="true" />
- networkConnectors>span>
上面这段配置需要加在节点的前面。然后在消费者应用中设置brokerURL的值如:
- <property name="brokerURL" value="<span style="color: #ff0000;">failover:(tcp://localhost:61617)span>?initialReconnectDelay=100" />
更加详细的说明与配置请参考:http://activemq.apache.org/networks-of-brokers.html
(2)Dynamic Discovery集群
官方地址:http://activemq.apache.org/static-transport-reference.html
Dynamic Discovery集群方式在配置ActiveMQ实例时,不需要知道所有其它实例的URI地址,只需在所有实例的${ACTIVEMQ_HOME}/conf/activemq.xml文件中添加以下内容:
- <span style="color: #ff0000;"><networkConnectors>
- <networkConnector uri="multicast://default" />
- networkConnectors>span>
同时在节点中添加以下红色部分内容:
- <transportConnectors>
- <transportConnector name="openwire" uri="tcp://0.0.0.0:61616" <span style="color: #ff0000;">discoveryUri="multicast://default"span> />
- transportConnectors>
这样就可以实现消息在所有ActiveMQ实例之间进行路由。Dynamic Discovery集群方式的缺点和Static Discovery一样。
从以上的分析可以看出,Master-Slave模式不支持负载均衡,但可以通过消息的实时备份或共享保证消息服务的可靠性,Broker Cluster模式支持负载均衡,可以提高消息的消费能力,但不能保证消息的可靠性。所以为了支持负载均衡,同时又保证消息的可靠性,我们可以采用Msater-Slave+Broker Cluster的模式。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/9399028/viewspace-1650271/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/9399028/viewspace-1650271/