ActiveMQ是一款功能强大的消息服务器,它支持许多种开发语言,例如Java, C, C++, C#等等。企业级消息服务

器无论对服务器稳定性还是速度,要求都很高,而ActiveMQ的分布式集群则能很好的满足这一需求,下面说说

ActiveMQ的几种集群配置。

Queue consumer clusters

此集群让多个消费者同时消费一个队列,若某个消费者出问题无法消费信息,则未消费掉的消息将被发给其他正常

的消费者,结构图如下:

activemq集群和springboot activemq集群老挂_高可用

一、activeMQ主要的几类部署方式比较

1、默认的单机部署(kahadb)

activeMQ的默认存储的单机方式,以本地kahadb文件的方式存储,所以性能指标完全依赖本地磁盘IO,不能提供

高可用。

2、基于zookeeper的主从(levelDB Master/Slave)

5.9.0新推出的主从实现,基于zookeeper来选举出一个master,其他节点自动作为slave实时同步消息。

因为有实时同步数据的slave的存在,master不用担心数据丢失,所以leveldb会优先采用内存存储消息,异步同

步到磁盘。所以该方式的activeMQ读写性能都最好,特别是写性能能够媲美非持久化消息。

优点:

实现高可用和数据安全

性能较好

缺点:

因为选举机制要超过半数,所以最少需要3台节点,才能实现高可用。

3、基于共享数据库的主从(Shared JDBC Master/Slave)

可以基于postgres、mysql、oracle等常用数据库。

每个节点启动都会争抢数据库锁,从而保证master的唯一性,其他节点作为备份,一直等待数据库锁的释放。

因为所有消息读写,其实都是数据库操作,activeMQ节点本身压力很小,性能完全取决于数据库性能。

优点:

实现高可用和数据安全

简单灵活,2台节点就可以实现高可用

缺点:

稳定性依赖数据库

性能依赖数据库
ActiveMQ 集群配置 高可用

自从activemq5.9.0开始,activemq的集群实现方式取消了传统的Pure Master Slave方式,增加了基于

zookeeper+leveldb的实现方式,其他两种方式:目录共享和数据库共享依然存在。

1、Master-Slave部署方式 

1)、Shared Filesystem Master-Slave方式 

2)、Shared Database Master-Slave方式

3)、Replicated LevelDB Store方式

第一种方案同样支持N个AMQ实例组网,但由于他是基于kahadb存储策略,亦可以部署在分布式文件系统上,应用

灵活、高效且安全。 

第二种方案与shared filesystem方式类似,只是共享的存储介质由文件系统改成了数据库而已,支持N个AMQ实

例组网,但他的性能会受限于数据库; 

第三种方案是ActiveMQ5.9以后才新增的特性,使用ZooKeeper协调选择一个node作为master。被选择的master 

broker node开启并接受客户端连接。 其他node转入slave模式,连接master并同步他们的存储状态。其他node

转入slave模式,连接master并同步他们的存储状态。如果master死了,得到了最新更新的slave被允许成为

master。fialed node能够重新加入到网络中并连接master进入slave mode。至于为什么是2-1,熟悉

Zookeeper的应该知道,有一个node要作为观擦者存在。
Shared Filesystem Master-Slave方式 

shared filesystem Master-Slave部署方式主要是通过共享存储目录来实现master和slave的热备,所有的

ActiveMQ应用都在不断地获取共享目录的控制权,哪个应用抢到了控制权,它就成为master。 

多个共享存储目录的应用,谁先启动,谁就可以最早取得共享目录的控制权成为master,其他的应用就只能作为

slave。 


一、下载activeMQ解压并复制3份

二、修改配置文件conf下面 activemq.xml

如下 ,3份文件broker都修改为一致  其中dataDirectory 是 数据存储共享目录地址

修改 kahaDB目录地址为数据存储共享目录地址

 修改openwire  的tcp 连接地址端口分别为 61616 61626 61636 

二 、修改conf 下面的 jetty.xml文件,修改管理界面端口 8161 8162 8163 方便测试查看启动的那一个

activemq服务

 三、启动  成功了一个后面的将阻塞等待获取锁
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
 
public class Receiver {
    public static void main(String[] args) {
        // ConnectionFactory :连接工厂,JMS 用它创建连接
        ConnectionFactory connectionFactory;
        // Connection :JMS 客户端到JMS Provider 的连接
        Connection connection = null;
        // Session: 一个发送或接收消息的线程
        Session session;
        // Destination :消息的目的地;消息发送给谁.
        Destination destination;
        // 消费者,消息接收者
        MessageConsumer consumer;
        connectionFactory = new ActiveMQConnectionFactory(
                "failover:(tcp://localhost:61616,tcp://localhost:61626,tcp://localhost:61636)");
        try {
            // 构造从工厂得到连接对象
            connection = connectionFactory.createConnection();
            // 启动
            connection.start();
            // 获取操作连接
            session = connection.createSession(Boolean.FALSE,
                    Session.AUTO_ACKNOWLEDGE);
            // 获取session注意参数值xingbo.xu-queue是一个服务器的queue,须在在ActiveMq的console配置
            destination = session.createQueue("FirstQueue");
            consumer = session.createConsumer(destination);
            while (true) {
                //设置接收者接收消息的时间,为了便于测试,这里谁定为100s
                TextMessage message = (TextMessage) consumer.receive(100000);
                if (null != message) {
                    System.out.println("收到消息" + message.getText());
                } else {
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != connection)
                    connection.close();
            } catch (Throwable ignore) {
            }
        }
    }
}
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
 
public class Sender {
    private static final int SEND_NUMBER = 5;
 
    public static void main(String[] args) {
        // ConnectionFactory :连接工厂,JMS 用它创建连接
        ConnectionFactory connectionFactory;
        // Connection :JMS 客户端到JMS Provider 的连接
        Connection connection = null;
        // Session: 一个发送或接收消息的线程
        Session session;
        // Destination :消息的目的地;消息发送给谁.
        Destination destination;
        // MessageProducer:消息发送者
        MessageProducer producer;
        // TextMessage message;
        // 构造ConnectionFactory实例对象,此处采用ActiveMq的实现jar
        connectionFactory = new ActiveMQConnectionFactory(
                "failover:(tcp://localhost:61616,tcp://localhost:61626,tcp://localhost:61636)");
        try {
            // 构造从工厂得到连接对象
            connection = connectionFactory.createConnection();
            // 启动
            connection.start();
            // 获取操作连接
            session = connection.createSession(Boolean.TRUE,
                    Session.AUTO_ACKNOWLEDGE);
            // 获取session注意参数值xingbo.xu-queue是一个服务器的queue,须在在ActiveMq的console配置
            destination = session.createQueue("FirstQueue");
            // 得到消息生成者【发送者】
            producer = session.createProducer(destination);
            // 设置不持久化,此处学习,实际根据项目决定 ---- 集群此处必须持久化
         //   producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
            // 构造消息,此处写死,项目就是参数,或者方法获取
            sendMessage(session, producer);
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != connection)
                    connection.close();
            } catch (Throwable ignore) {
            }
        }
    }
 
    public static void sendMessage(Session session, MessageProducer producer)
            throws Exception {
        for (int i = 1; i <= SEND_NUMBER; i++) {
            TextMessage message = session
                    .createTextMessage("ActiveMq 发送的消息" + i);
            // 发送消息到目的地方
            System.out.println("发送消息:" + "ActiveMq 发送的消息" + i);
            producer.send(message);
        }
    }
}