activeMq

1.activeMq简介:

ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现。

2.JMS1.1规范相关概念:jms(Java Message Service)

  • 提供者:实现JMS规范的消息中间件服务器.
  • 客户端:发送或者接受消息的应用程序.
  • 生产者/发布者:创建并发送消息客户端.
  • 消费者/订阅者:接收并处理消息的客户端.
  • 消息:应用程序之间传递数据内容.
  • 消息模式:在客户端之间传递消息的方式,JMS中定义了主题和队列两种模式.

 3.JMS的消息模式:

3.1.队列模型

  • 客户端包括生产者和消费者
  • 队列中的消息只能被一个消费者消费.
  • 消费者可以随时消费队列中的消息.
    队列模型中,消费者的每个连接会依次接收JMS队列中的消息.每个连接接收到的是不同的消息

3.2.主题模式

  • 客户端包括发布者和订阅者
  • 主题中的消息被所有订阅者消费
  • 消费者不能消费订阅之前就发送到主题中的消息.每个消费者收到的是全部的消息

4.JMS编码接口

  • ConnectionFactory:用于创建连接到消息中间件的连接工厂.
  • Connection:代表了应用程序和消息服务之间的通讯链路.
  • Destination:目的地,指消息发布和接收的地点,包括队列和主题.
  • Session:表示一个单线程的上下文,用于发送和接收消息.
  • MessageConsumer:由会话创建,用于接收发送到目标的主题和消息.
  • MessageProducer:由会话创建,用于发送消息到目标.
  • Message:是消息体,是在生产者和消费者之间传递的对象,由消息头(必须存在),消息属性,消息体组成.

 

 5.activeMq的应用场景

异步处理,应用解耦,流量削峰,消息通讯

5.1.异步处理:用户注册后,发送邮件和短信告诉其注册成功

传统方式:串行处理,1.先将用户信息持久化到数据库,2.发送邮件,3.发送短信。

消息队列:异步处理,1.将用户信息持久化到数据库,2.将提醒相关信息放入队列,进行异步通知。加快响应时间。

5.2.应用解耦:用户下单后,订单系统需要通知库存系统。

传统方式:订单系统调用库存系统的接口,增加系统间的耦合度。

存在的问题:1.订单系统调用库存系统失败,导致订单失败。

消息队列:1.订单系统:用户下单后,订单系统将数据持久化到数据库,将消息写入消息队列,返回用户订单下单成功,请等待物流配送的提示信息

2.库存系统:订阅下单的消息,采用 发布/订阅 的方式,获取下单信息,库存系统根据下单信息,进行减库存操作。

解决库存系统失败导致订单失败的问题,订单系统将订单信息持久化到数据库,向队列发布一条消息,至此订单系统的操作完成,库存系统通过定阅消息进行相关操作。库存系统出现问题将不会影响到订单系统,实现系统间的解耦。

5.3.流量削锋:秒杀

流量过大,导致系统崩溃的问题。在用户请求到达秒杀系统之前放入队列,超过队列最大数量的请求抛弃,秒杀系统根据队列中的消息进行后续的相关处理,控制了并发量。

5.4.消息通讯:点对点,群发

6.P2P(queue)

消息生产者生产消息发送到 queue 中,然后消息消费者从 queue 中取出并且消费消息。消息被消费以后,queue 中不再有存储,所以消息消费者不可能消费到已经被消费的消息。Queue 支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费、其它的则不能消费此消息了。当消费者不存在时,消息会一直保存,直到有消费消费。

创建生产者代码

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

public class Producter {

    //ActiveMq 的默认用户名
    private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;
    //ActiveMq 的默认登录密码
    private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;
    //ActiveMQ 的链接地址
    private static final String BROKEN_URL = "tcp://192.168.180.128:61616";

    //链接工厂
    ConnectionFactory connectionFactory;
    //链接对象
    Connection connection;
    //事务管理
    Session session;
    //消息生产者
    MessageProducer messageProducer;

    public void init() {
        try {
            //创建一个链接工厂
            connectionFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKEN_URL);
            //从工厂中创建一个链接
            connection = connectionFactory.createConnection();
            //开启链接
            connection.start();
            //创建一个事务(通过参数可以设置事务的级别)
            session = connection.createSession(true, Session.SESSION_TRANSACTED);
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }

    public void sendMessage(String disname) {
        try {
            //创建一个消息队列
            Queue queue = session.createQueue(disname);
            //消息生产者
            messageProducer = session.createProducer(queue);
            //创建一条消息
            TextMessage msg = session.createTextMessage("message");
            //发送消息
            messageProducer.send(msg);
            //提交事务
            session.commit();
            System.out.println("消息发送完成!");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //回收资源
            if (messageProducer != null) {
                try {
                    messageProducer.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            if (session != null) {
                try {
                    session.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

消费者代码:

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

public class Comsumer {

    private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;

    private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;

    private static final String BROKEN_URL = "tcp://192.168.180.128:61616";

    ConnectionFactory connectionFactory;

    Connection connection;

    Session session;
    MessageConsumer consumer;


    public void init() {
        try {
            connectionFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKEN_URL);
            connection = connectionFactory.createConnection();
            connection.start();
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }


    public void getMessage(String disname) {
        try {
            Queue queue = session.createQueue(disname);
            consumer = session.createConsumer(queue);
            TextMessage msg = (TextMessage) consumer.receive();
            if (msg != null) {
                msg.acknowledge();
                System.out.println("Consumer:" + msg.getText());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (consumer != null) {
                try {
                    consumer.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            if (session != null) {
                try {
                    session.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }

        }
    }

}

 生产者测试代码:

public class TestProducer {
    public static void main(String[] args){
        Producter producter = new Producter();
        producter.init();
        producter.sendMessage("queue1");
    }
}

消费者测试代码:

public class TestConsumer {
    public static void main(String[] args) {
        Comsumer comsumer = new Comsumer();
        comsumer.init();
        comsumer.getMessage("queue1");
    }
}

 结果:

activeMq管理页面(启动消费者前)

 启动消费者后:

 

7.Publish/Subscribe  处理模式(Topic )

消息生产者(发布)将消息发布到 topic 中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到 topic 的消息会被所有订阅者消费。当生产者发布消息,不管是否有消费者。都不会保存消息一定要先有消息的消费者,后有消息的生产者。

 生产者代码:

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

/**
 * Desc:
 * Created By zhangyh On 2018-10-13
 */
public class Producer {
    //密码
    private static final String PASSWORD = "admin";
    //用户名
    private static final String USERNAME = "admin";
    //连接
    private static final String ACTIVEMQ_URL = "tcp://127.0.0.1:61616";
    //连接工厂
    ConnectionFactory connectionFactory;
    //连接
    Connection connection;
    //回话
    Session session;
    //生产者
    MessageProducer producer;
    //topic主题目的地
    Destination destination;


    public void sendMessage() {
        try {
            connectionFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, ACTIVEMQ_URL);
            Connection connection = connectionFactory.createConnection();
            connection.start();
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            destination = session.createTopic("topic1");
            MessageProducer producer = session.createProducer(destination);
            Message message = session.createTextMessage("data");
            producer.send(message);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (producer != null) {
                try {
                    producer.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            if (session != null) {
                try {
                    session.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        Producer producer = new Producer();
        producer.sendMessage();
        System.out.println("发送成功!!");
    }
}

消费者代码:

import javax.jms.*;

/**
 * Desc:
 * Created By zhangyh On 2018-10-13
 */
public class Consumer {
    //密码
    private static final String PASSWORD = "admin";
    //用户名
    private static final String USERNAME = "admin";
    //连接
    private static final String ACTIVEMQ_URL = "tcp://127.0.0.1:61616";
    //连接工厂
    ConnectionFactory connectionFactory;
    //连接
    Connection connection;
    //回话
    Session session;
    //生产者
    MessageConsumer consumer;
    //topic主题目的地
    Destination destination;


    public void getMessage() {
        try {
            connectionFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, ACTIVEMQ_URL);
            Connection connection = connectionFactory.createConnection();
            connection.start();
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            destination = session.createTopic("topic1");
            MessageConsumer consumer = session.createConsumer(destination);
            Message message = consumer.receive();
            TextMessage textMessage = (TextMessage) message;
            System.out.println(textMessage.getText());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (consumer != null) {
                try {
                    consumer.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            if (session != null) {
                try {
                    session.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        Consumer consumer = new Consumer();
        consumer.getMessage();
    }
}

先启动两个消费者对消息进行订阅

启动生产者发布消息:

activeMq控制台:

 

两种模式的对比:

8.activeMq的安全认证

 

9.activeMq的持久化

ActiveMQ 中,持久化是指对消息数据的持久化。在 ActiveMQ 中,默认的消息是保存在内存中的。当内存容量不足的时候,或 ActiveMQ 正常关闭的时候,会将内存中的未处理的消息持久化到磁盘中。具体的持久化策略由配置文件中的具体配置决定。
ActiveMQ 的默认存储策略是 kahadb。如果使用 JDBC 作为持久化策略,则会将所有的需要持久化的消息保存到数据库中。
所有的持久化配置都在 conf/activemq.xml 中配置,配置信息都在 broker 标签内部定义。

三种持久化方式:KAHADB、AMQ、JDBC

9.1 kahadb:

ActiveMQ 默认的持久化策略。kahadb 是一个文件型数据库。是使用内存+文件保证数据的持久化的。kahadb 可以限制每个数据文件的大小。不代表总计数据容量。特性是:1、日志形式存储消息;2、消息索引以 B-Tree 结构存储,可以快速更新;3、完全支持 JMS 事务;4、支持多种恢复机制

9.2 AMQ:

只适用于 5.3 版本之前。AMQ 也是一个文件型数据库,消息信息最终是存储在文件中。内存中也会有缓存数据。性能高于JDBC,写入消息时,会将消息写入日志文件,由于是顺序追加写,性能很高。为了提升性能,创建消息主键索引,并且提供缓存机制,进一步提升性能。每个日志文件的大小都是有限制的(默认 32m,可自行配置)。当超过这个大小,系统会重新建立一个文件。当所有的消息都消费完成,系统会删除这个文件或者归档。主要的缺点是 AMQ Message 会为每一个 Destination 创建一个索引,如果使用了大量的Queue,索引文件的大小会占用很多磁盘空间。而且由于索引巨大,一旦 Broker(ActiveMQ 应用实例)崩溃,重建索引的速度会非常慢。虽然 AMQ 性能略高于 Kaha DB 方式,但是由于其重建索引时间过长,而且索引文件
占用磁盘空间过大,所以已经不推荐使用。

9.3 JDBC:

ActiveMQ 将数据持久化到数据库中。 不指定具体的数据库。 可以使用任意的数据库

 

10.activeMq集群

 

11.activeMq,RabbitMq,RocketMq,kafka对比

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值