ActiveMQ的集群
为什么要进行集群呢?
原因一:实现高可用:以排除单点故障所引起的服务终端。
原因二:实现负载均衡:以提升效率为更多的客户进行服务。
集群的方式有哪些?
方式一:客户端集群:多个客户端消费同一个队列。
方式二:Broker clusters:多个Broker之间同步消息。(实现负载均衡)
网络连接器:用于配置ActiveMQ服务器与服务器之间的网络通讯方式,用于服务器透析消息。主要分为静态连接和动态连接。
方式三:Master Slave :实现高可用。 这种方式的话,可以联想到Mysql的主从配置和Zookeeper的负载均衡的主竞争关系master。
我们在实际的开发中,一般都是将方式二和方式三进行集成,从而实现高可用和负载均衡。下面的话,我也就这样的配置思想来进行讲解:(通过三台服务器来模拟消息集群的实现)
搭建步骤(基于Windows环境,而Linux环境也是一样的操作) 三台服务器的大体功能和描述:
由于自己没有三台服务器,所以就用自己的一台电脑来模拟三台消息服务器,其实这个就是假设有三个不同ActiveMQ消息服务器了。
1. 复制三个ActiveMQ的服务配置到一个公共目录
2. 修改activeMQA的配置文件
只需要在activemq.xml添加如下内容:
<networkConnectors>
<networkConnector name="local_network" uri ="static:(tcp://127.0.0.1:61617,tcp://127.0.0.1:61618)" />
</networkConnectors>
3. 修改ActiveMQB的配置文件
(1)首先在activemq,xml中添加如下内容:
<!--修改服务端口-->
<transportConnector name="openwire" uri="tcp://0.0.0.0:61617?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<networkConnectors>
<networkConnector name="networktoA" uri="static:(tcp://127.0.0.1:61616)" />
</networkConnectors>
<!--并修改下面这个标签的内容 , 作为B和C的共享文件,目录就是自己之前创建的一个文件(可以回看上面的整个结构)-->
<persistenceAdapter>
<kahaDB directory="D:\Download\MQJiQun\shareDB"/>
</persistenceAdapter>
(2)修改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="8162"/>
</bean>
4. 修改ActiveMQC的配置文件(其实类似和B一样,只是服务端口不一样)
(1)修改activemq.xml中的内容 。
<!--修改服务端口-->
<transportConnector name="openwire" uri="tcp://0.0.0.0:61618?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<networkConnectors>
<networkConnector name="networktoA" uri="static:(tcp://127.0.0.1:61616)" />
</networkConnectors>
<!--并修改下面这个标签的内容 , 作为B和C的共享文件,目录就是自己之前创建的一个文件(可以回看上面的整个结构)-->
<persistenceAdapter>
<kahaDB directory="D:\Download\MQJiQun\shareDB"/>
</persistenceAdapter>
(2)修改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="8163"/>
</bean>
5. 集群搭建完成~~~~
集群测试(基于IDEA编辑器+Maven)
步骤:
(1)创建Maven项目
(2)导入依赖
<!--添加activemq的依赖-->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.9.0</version>
</dependency>
(3)编写生产者代码
package com.hnu.scw.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
/**
* @ Author :scw
* @ Date :Created in 上午 11:06 2018/7/14 0014
* @ Description:用于消息的创建类
* @ Modified By:
* @Version: $version$
*/
public class MessageProducer {
//通过集群的方式进行消息服务器的管理(failover就是进行动态转移,当某个服务器宕机,
// 那么就进行其他的服务器选择,randomize表示随机选择)
private static final String ACTIVEMQ_URL = "failover:(tcp://127.0.0.1:61617,tcp://127.0.0.1:61618)?randomize=true";
//定义发送消息的队列名称
private static final String QUEUE_NAME = "MyMessage";
public static void main(String[] args) throws JMSException {
//创建连接工厂
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//创建连接
Connection connection = activeMQConnectionFactory.createConnection();
//打开连接
connection.start();
//创建会话
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建队列目标
Destination destination = session.createQueue(QUEUE_NAME);
//创建一个生产者
javax.jms.MessageProducer producer = session.createProducer(destination);
//创建模拟100个消息
for (int i = 1 ; i <= 100 ; i++){
TextMessage message = session.createTextMessage("当前message是:" + i);
//发送消息
producer.send(message);
//在本地打印消息
System.out.println("我现在发的消息是:" + message.getText());
}
//关闭连接
connection.close();
}
}
(4)编写消费者代码 。
package com.hnu.scw.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
/**
* @ Author :scw
* @ Date :Created in 上午 11:30 2018/7/14 0014
* @ Description:消息消费者
* @ Modified By:
* @Version: $version$
*/
public class MessageConsumer {
//通过集群的方式进行消息服务器的管理(failover就是进行动态转移,当某个服务器宕机,
// 那么就进行其他的服务器选择,randomize表示随机选择)
private static final String ACTIVEMQ_URL = "failover:(tcp://127.0.0.1:61616,tcp://127.0.0.1:61617,tcp://127.0.0.1:61618)?randomize=true";
//定义发送消息的队列名称
private static final String QUEUE_NAME = "MyMessage";
public static void main(String[] args) throws JMSException {
//创建连接工厂
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//创建连接
Connection connection = activeMQConnectionFactory.createConnection();
//打开连接
connection.start();
//创建会话
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建队列目标
Destination destination = session.createQueue(QUEUE_NAME);
//创建消费者
javax.jms.MessageConsumer consumer = session.createConsumer(destination);
//创建消费的监听
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("获取消息:" + textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
}
}
(5)进行查看各自的服务器的消息队列的情况。
1. 首先,是要确保三个ActiveMQ服务器都进行打开。分析:当三个都服务都运行之后,我们从浏览器运行各自的地址,会发现: 比如:我这里的三个服务的地址分别如下:
– http://127.0.0.1:8161/
– http://127.0.0.1:8162/
– http://127.0.0.1:8163/
重点 为什么前面两个都可以访问,而第三个不可以呢?(同样也是按照我的这样的服务器打开方式哦。先打开的服务器A,接着B,最后C)但是,运行的时候,提示都成功了呀。。为什么为什么???
分析:
其实很简单,我说过B和C是一种master/slave的方式,当B运行之后就获得了master的权限,那么C服务是可以看到是一种监听的状态,只有当B宕机之后,才有可能获取master的资源权限,所以,这时候C的地址当然就无法访问啦。这就是负载均衡的一种主/从服务的结构。当然,你可以试着先打开C,再打开B,这时候效果就反过来了。欢迎尝试哦~~~
2. 再运行MessageProducer的类,用于产生消息。这时候,大家可以去查看每个服务器的地址,来观察消息的产生情况。我的消息是产生在服务器B的里面啦(通过访问各个服务器的地址URL)。。。。。。
3. 再运行MessageConsumer的类,用于消费消息。这时候,同样可以去查看每个服务器的地址中的消息队列的情况,来观察消息的消费情况。
4. 如果,我们在生产者产生了消息之后,服务器B突然宕机了怎么办怎么办??
分析:
其实,这时候服务器C就一样有消息保存进行同步了。。是不是这样就是一种高可用的架构了呢????大家,可以试试哦。。把B服务器关掉,再去访问服务器C的地址,就发现如下的结果。
这时候服务器C就作为了master,所以,类似zookeeper就是这样的一种方式的哦。~
总结
好了,对于集群方面的简单使用就到这里了。其实已经可以根据这个进行扩展了,所以,小伙伴要好好理解这里面的过程和作用,这样才能够学以致用。。。
具体的话,大家可以通过这个链接进行访问原文(格式更加友好一些啦,并且包含了ActiveMQ的入门知识):
感谢各位的阅读浏览~~~共同学习,进步~~~