ActiveMQ有很多种集群方式,包括Queue consumer clusters、Broker clusters、Discovery of brokers、Networks of brokers、Master Slave、Replicated Message Stores。
其中Master Slave集群有四种实现方式,包括Pure Master Slave、Shared File System Master Slave、JDBC Master Slave和Replicated LevelDB Store。
下面详细介绍这些集群方式的实现过程。
一、Queue consumer clusters
一个队列有多个消费者,每个消费者是平等的,他们一起竞争队列中的消息,当一个消费者挂掉时,消息会被其他消费者接收,这样可以实现队列消息的高可用性和负载均衡。
二、Broker clusters
联合多个Broker结点实现集群,使用故障转移协议failover,当集群中的broker结点挂掉时,客户端会自动连接到集群中的其他broker结点。
三、Discovery of brokers
通过静态发送或动态发现,来自动发现集群中的brokers,客户端能自动检测和连接集群中的broker.
四、Networks of brokers
这种集群方式可以支持某个broker中的消费者去接收其他broker中的消息,从而实现负载均衡、提高系统吞吐量。
比如客户端clientA发送消息到brokerA上的队列queueA,客户端clientB连接brokerB上的队列queueA,这时brokerA上队列queueA的消息就会自动路由到brokerB上的队列queueA上,也就是说clientB可以间接读取brokerA的队列queueA上的消息。
下面创建一个包含三个broker的Network of brokers集群。
1.修改三个broker节点的配置文件activemq.xml
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="network_of_brokers_01">
<networkConnectors>
<networkConnector uri="static:(tcp://localhost:61616,tcp://localhost:61617,tcp://localhost:61618)"
name="bridge01"
duplex="true"
dynamicOnly="false"
conduitSubscriptions="true"
decreaseNetworkConsumerPriority="false"
/>
</networkConnectors>
<transportConnectors>
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616"/>
</transportConnectors>
</broker>
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="network_of_brokers_02">
<networkConnectors>
<networkConnector uri="static:(tcp://localhost:61616,tcp://localhost:61617,tcp://localhost:61618)"
name="bridge01"
duplex="true"
dynamicOnly="false"
conduitSubscriptions="true"
decreaseNetworkConsumerPriority="false"
/>
</networkConnectors>
<transportConnectors>
<transportConnector name="openwire" uri="tcp://0.0.0.0:61617"/>
</transportConnectors>
</broker>
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="network_of_brokers_01">
<networkConnectors>
<networkConnector uri="static:(tcp://localhost:61616,tcp://localhost:61617,tcp://localhost:61618)"
name="bridge01"
duplex="true"
dynamicOnly="false"
conduitSubscriptions="true"
decreaseNetworkConsumerPriority="false"
/>
</networkConnectors>
<transportConnectors>
<transportConnector name="openwire" uri="tcp://0.0.0.0:61618"/>
</transportConnectors>
</broker>
2.消息接收者
package com.activemq;
import java.util.Date;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* ActiveMQ 接收消息
* @author brushli
* @date 2014-12-05
*/
public class Receiver {
private static final Logger logger = LoggerFactory.getLogger(Receiver.class);
public void receiveMessage(){
Connection connection = null;
Session session = null;
try {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD, "failover:(tcp://127.0.0.1:61616,tcp://127.0.0.1:61617,tcp://127.0.0.1:61618)");
connection = connectionFactory.createConnection();
connection.start();
//(parameter a:是否支持事务,parameter b:消息应答模式)
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("cluster_queue");
MessageConsumer consumer = session.createConsumer(destination);
logger.info("begin to receive Message! currentTime="+new Date().toLocaleString());
while (true) {
//设置接收者接收消息的时间,为了便于测试,这里谁定为100s
TextMessage message = (TextMessage) consumer.receive();
if (null != message) {
logger.info("receive message[" + message.getText()+"] ");
}
}
} catch (JMSException e) {
e.printStackTrace();
}finally{
try {
session.close();
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Receiver receiver = new Receiver();
receiver.receiveMessage();
}
}
3.消息发送者
package com.activemq;
import java.util.Date;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* ActiveMQ 发送消息
* @author brushli
* @date 2014-12-05
*/
public class Sender {
private static final Logger logger = LoggerFactory.getLogger(Sender.class);
public void sendMessage(){
try {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD, "failover:(tcp://127.0.0.1:61616,tcp://127.0.0.1:61617,tcp://127.0.0.1:61618)");
Connection connection = connectionFactory.createConnection();
connection.start();
//(parameter a:是否支持事务,parameter b:消息应答模式)
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("cluster_queue");
//创建什么什么模式的生产者,可选参数: Queue, TemporaryQueue, TemporaryTopic, Topic
MessageProducer producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
logger.info("begin to send Message! currentTime="+new Date().toLocaleString());
for(int i=1; i<=10; i++) {
TextMessage message = session.createTextMessage();
message.setText("message" + i);
producer.send(message);
Thread.sleep(5000);
logger.info("send message [" + "message" + i +"]");
}
logger.info("send Message finished! currentTime="+new Date().toLocaleString());
session.close();
connection.close();
} catch (JMSException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Sender sender = new Sender();
sender.sendMessage();
}
}
4.测试步骤
(1)启动三个消费者
ActiveMQ01 broker01
2014-12-10 10:04:05 INFO FailoverTransport.doReconnect: 1030 - Successfully connected to tcp://127.0.0.1:61616
ActiveMQ02 broker02
2014-12-10 10:04:07 INFO FailoverTransport.doReconnect: 1030 - Successfully connected to tcp://127.0.0.1:61617
ActiveMQ03 broker03
2014-12-10 10:04:08 INFO FailoverTransport.doReconnect: 1030 - Successfully connected to tcp://127.0.0.1:61618
(2)启动发送者
发送十条消息
2014-12-10 10:04:10 INFO FailoverTransport.doReconnect: 1030 - Successfully connected to tcp://127.0.0.1:61618
2014-12-10 10:04:10 INFO Sender.sendMessage: 39 - begin to send Message! currentTime=2014-12-10 10:04:10
2014-12-10 10:04:15 INFO Sender.sendMessage: 45 - send message [message1]
2014-12-10 10:04:20 INFO Sender.sendMessage: 45 - send message [message2]
2014-12-10 10:04:25 INFO Sender.sendMessage: 45 - send message [message3]
2014-12-10 10:04:30 INFO Sender.sendMessage: 45 - send message [message4]
2014-12-10 10:04:35 INFO Sender.sendMessage: 45 - send message [message5]
2014-12-10 10:04:40 INFO Sender.sendMessage: 45 - send message [message6]
2014-12-10 10:04:45 INFO Sender.sendMessage: 45 - send message [message7]
2014-12-10 10:04:50 INFO Sender.sendMessage: 45 - send message [message8]
2014-12-10 10:04:55 INFO Sender.sendMessage: 45 - send message [message9]
2014-12-10 10:05:00 INFO Sender.sendMessage: 45 - send message [message10]
2014-12-10 10:05:00 INFO Sender.sendMessage: 47 - send Message finished! currentTime=2014-12-10 10:05:00
(3)三个消费者接收消息
消费者01,连接ActiveMQ01 broker01
2014-12-10 10:04:05 INFO FailoverTransport.doReconnect: 1030 - Successfully connected to tcp://127.0.0.1:61616
2014-12-10 10:04:05 INFO Receiver.receiveMessage: 39 - begin to receive Message! currentTime=2014-12-10 10:04:05
2014-12-10 10:04:10 INFO Receiver.receiveMessage: 44 - receive message[message1]
2014-12-10 10:04:15 INFO Receiver.receiveMessage: 44 - receive message[message2]
2014-12-10 10:04:35 INFO Receiver.receiveMessage: 44 - receive message[message6]
2014-12-10 10:04:40 INFO Receiver.receiveMessage: 44 - receive message[message7]
消费者02,连接ActiveMQ02 broker02
2014-12-10 10:04:07 INFO FailoverTransport.doReconnect: 1030 - Successfully connected to tcp://127.0.0.1:61617
2014-12-10 10:04:07 INFO Receiver.receiveMessage: 39 - begin to receive Message! currentTime=2014-12-10 10:04:07
2014-12-10 10:04:20 INFO Receiver.receiveMessage: 44 - receive message[message3]
2014-12-10 10:04:25 INFO Receiver.receiveMessage: 44 - receive message[message4]
2014-12-10 10:04:45 INFO Receiver.receiveMessage: 44 - receive message[message8]
2014-12-10 10:04:50 INFO Receiver.receiveMessage: 44 - receive message[message9]
消费者03,连接ActiveMQ03 broker03
2014-12-10 10:04:08 INFO FailoverTransport.doReconnect: 1030 - Successfully connected to tcp://127.0.0.1:61618
2014-12-10 10:04:08 INFO Receiver.receiveMessage: 39 - begin to receive Message! currentTime=2014-12-10 10:04:08
2014-12-10 10:04:30 INFO Receiver.receiveMessage: 44 - receive message[message5]
2014-12-10 10:04:55 INFO Receiver.receiveMessage: 44 - receive