• 以ActiveMQ为例JAVA消息中间件学习【1】


    前言

    在慢慢的接触大型的javaweb的项目就会接触到很多的中间件系统。

    其中消息中间件在很多场景下会被运用。

    这里主要就对最近所学习到的消息中间件知识做一个笔记,为以后的实际运用打下一个良好的基础。

    什么是中间件,什么是消息中间件

    最近被很多人问到,所以这里解释一下,我只是讲我的理解,也没有什么官方的定义。所谓中间件,顾名思义,是在一个过程中中间使用的元件。具体一点说:在整个业务系统中,用户看不到,但是也不是最底层的操作,在中间实现桥梁作用的技术或者是软件都可以称为中间件。

    那么消息中间件,重点就在消息上面了。

    消息就存在两个步骤,第一个步骤是发送,第二个步骤是接收,而这个两个步骤是异步的。完成这两个步骤的中间件就是消息中间件了。

    听到这里你肯定还不是很明白。我就比较的并且白话的来说。

    没有消息中间件,那就是我告诉你做什么,你就马上做什么,就像我们写的普通的接口服务一样。

    有消息中间件,那就是,我告诉中间件你要做什么,我的中间件发送消息给你的中间件,你的中间件收到消息告诉你,你再开始做。

    要是再不理解也没关系,继续看下去。

    什么是JMS,什么是AMQP

    java message service(java消息服务)

    面向消息中间件的API,用于发送消息,进行异步通信

    AMQP是一个提供统一消息的应用层标准协议,是一个统一的消息模型,为了跨平台而生。

    简单的说,因为发送消息必须先要有规定,就和HTTP一样,要通信就必须要有协议去规定(规定消息怎么发,消息长成什么样等),而JMS是针对与java的协议,而AMQP是面向应用的协议。

    几种消息中间件

    image

    JMS中的相关称呼

    提供者:提供服务的中间件服务器

    客户端:发送和接收消息的应用程序

    生产者、发布者:创建并发送消息的客户端

    消费者、订阅者:接受并处理消息的客户端

    消息:传送的数据内容

    消息模式:不同的消息模式对应不同的消息传递方式

    队列模式:

    队列中的消息只能被一个消费者消费

    消费者可以随时消费队列中的消息

    主题模式:

    消息被所有订阅者消费,每个订阅者都能收到消息,就和我们现在的微博一样,只要你关注了,那就能都能收到消息。

    消费者不能消费之前发送主题的消息,也就是说在你订阅之后才会收到消息,但是之前的历史消息你是看不到的。

    ConnectionFactory:用于创建连接到消息中间件的连接工厂

    Connection:代表应用程序和消息服务器之间的通信链路

    Destination:消息发布和接收的地点

    Session:会话,表示一个单线程的上下文,用于发送和接收消息

    MessageConsumer:由会话创建,用于接收发送到目标的消息

    MessageProducer:由会话创建,用于发送消息到目标

    Message:是在消费者和生产者之间传送的对象,消息头,一组消息属性,一个消息体

    上面所有类的关系

    image

    简单的实现(队列模式)

    我们使用ActiveMQ进行实现

    下载地址:http://activemq.apache.org/download.html

    解压后找到inwin64目录下的activemq.bat直接运行即可

    使用maven导入依赖

    <dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-all</artifactId>
    <version>5.9.0</version>
    </dependency>
     
    编写消息的提供者
    import org.apache.activemq.ActiveMQConnectionFactory;
    
    import javax.jms.*;
    
    /**
     * 消息的提供者
     */
    public class Producer {
        //ActiveMQ的地址
        private static final String URL = "tcp://127.0.0.1:61616";
        //队列的名字
        private static final String QUEUE_NAME = "active-test_queue";
    
        public static void main(String[] args) throws JMSException {
            //1、创建工厂
            ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(URL);
    
            //2、创建连接
            Connection connection = connectionFactory.createConnection();
    
            //3、启动连接
            connection.start();
    
            //4、创建会话
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    
            //5、创建目的地
            Destination destination = session.createQueue(QUEUE_NAME);
    
            //6、创建一个生产者
            MessageProducer producer = session.createProducer(destination);
    
            for (int i = 0; i < 10; i++) {
                //7、创建消息
                TextMessage textMessage = session.createTextMessage("testMessage " + i);
                //8、发送消息
                producer.send(destination, textMessage);
                System.out.println("发送消息:" + textMessage.getText());
            }
    
            //9、关闭连接
            connection.close();
        }
    }

    然后运行

     

    本地ActiveMQ访问地址是

    http://127.0.0.1:8161/

    点击Manage ActiveMQ broker

    帐号密码都是admin

    然后点击上面的

    image

    image

    其中10就是我们发送的10条消息

    然后我们编写消费者

    import org.apache.activemq.ActiveMQConnectionFactory;
    
    import javax.jms.*;
    
    /**
     * 消息的消费者
     */
    public class Consumer {
        //ActiveMQ的地址
        private static final String URL = "tcp://127.0.0.1:61616";
        //队列的名字
        private static final String QUEUE_NAME = "active-test_queue";
    
        public static void main(String[] args) throws JMSException {
            //1、创建工厂
            ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(URL);
    
            //2、创建连接
            Connection connection = connectionFactory.createConnection();
    
            //3、启动连接
            connection.start();
    
            //4、创建会话
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    
            //5、创建目的地
            Destination destination = session.createQueue(QUEUE_NAME);
    
            //6、创建一个消费者
            MessageConsumer messageConsumer = session.createConsumer(destination);
    
            //7、创建一个监听器
            messageConsumer.setMessageListener(new MessageListener() {
                public void onMessage(Message message) {
                    TextMessage textMessage = (TextMessage) message;
                    try {
                        System.out.println("接收到消息" + textMessage.getText());
                    } catch (JMSException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    然后运行之后查看队列中的消息

    image

    可以看到已经被消费了

    当我们启动多个消费者,然后再启动生产者,我们可以看到在队列模式下一个消息只能被一个消费者消费

    第一个

    接收到消息testMessage 0
    接收到消息testMessage 3
    接收到消息testMessage 6
    接收到消息testMessage 9

    第二个

    接收到消息testMessage 1
    接收到消息testMessage 4
    接收到消息testMessage 7

    第三个

    接收到消息testMessage 2
    接收到消息testMessage 5
    接收到消息testMessage 8

    简单的实现(主题模式)

    代码上面就改动一点点

    /**
     * 消息的提供者
     */
    public class Producer {
        //ActiveMQ的地址
        private static final String URL = "tcp://127.0.0.1:61616";
        //主题的名字
        private static final String TOPIC_NAME = "active-test_topic";
    
        public static void main(String[] args) throws JMSException {
            //1、创建工厂
            ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(URL);
    
            //2、创建连接
            Connection connection = connectionFactory.createConnection();
    
            //3、启动连接
            connection.start();
    
            //4、创建会话
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    
            //5、创建目的地
            Destination destination = session.createTopic(TOPIC_NAME);
    
            //6、创建一个生产者
            MessageProducer producer = session.createProducer(destination);
    
            for (int i = 0; i < 10; i++) {
                //7、创建消息
                TextMessage textMessage = session.createTextMessage("testMessage " + i);
                //8、发送消息
                producer.send(destination, textMessage);
                System.out.println("发送消息:" + textMessage.getText());
            }
    
            //9、关闭连接
            connection.close();
        }
    }
    /**
     * 消息的订阅者
     */
    public class Consumer {
        //ActiveMQ的地址
        private static final String URL = "tcp://127.0.0.1:61616";
        //主题的名字
        private static final String TOPIC_NAME = "active-test_topic";
    
        public static void main(String[] args) throws JMSException {
            //1、创建工厂
            ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(URL);
    
            //2、创建连接
            Connection connection = connectionFactory.createConnection();
    
            //3、启动连接
            connection.start();
    
            //4、创建会话
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    
            //5、创建目的地
            Destination destination = session.createTopic(TOPIC_NAME);
    
            //6、创建一个消费者
            MessageConsumer messageConsumer = session.createConsumer(destination);
    
            //7、创建一个监听器
            messageConsumer.setMessageListener(new MessageListener() {
                public void onMessage(Message message) {
                    TextMessage textMessage = (TextMessage) message;
                    try {
                        System.out.println("接收到消息" + textMessage.getText());
                    } catch (JMSException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    然后我们先启动消息的发送者,然后再启动订阅者试试

    我们发现订阅者没有接收到任何消息,因为在主题模式下只有先订阅再接收,你是不能收到一个主题下的历史消息的。

    然后我们关闭所有,然后启动两个订阅者,然后再启动发送者。

    我们看到

    第一个

    接收到消息testMessage 0
    接收到消息testMessage 1
    接收到消息testMessage 2
    接收到消息testMessage 3
    接收到消息testMessage 4
    接收到消息testMessage 5
    接收到消息testMessage 6
    接收到消息testMessage 7
    接收到消息testMessage 8
    接收到消息testMessage 9

    第二个

    接收到消息testMessage 0
    接收到消息testMessage 1
    接收到消息testMessage 2
    接收到消息testMessage 3
    接收到消息testMessage 4
    接收到消息testMessage 5
    接收到消息testMessage 6
    接收到消息testMessage 7
    接收到消息testMessage 8
    接收到消息testMessage 9

    说明在主题模式下,每一个订阅者都会收到一条一模一样的消息。

    总结

    至此我们已经可以简单的使用ActiveMQ了。我们第一阶段也就完成了。

    思考几个问题,我们需要熟悉整个过程,在整个过程中那些东西是会被多次使用的,那些使用后马上需要关闭,而那些是不能马上关闭的?

    主题模式和队列模式分别应该应用在实际中的哪种场景?

    后面我们会慢慢继续学习。

  • 相关阅读:
    LeetCode算法题-Binary Search(Java实现)
    LeetCode算法题-Kth Largest Element in a Stream(Java实现)
    LeetCode算法题-Search in a Binary Search Tree(Java实现)
    LeetCode算法题-Degree of an Array(Java实现)
    LeetCode算法题-Count Binary Substrings(Java实现)
    LeetCode算法题-Binary Number with Alternating Bits(Java实现)
    之前见汤姆大叔 写过一系列的 js 深入理解 呢 很是感觉经典
    xsd 和 wsdl
    发现 一个业务管理系统 解决了 orm 和 前端框架 剩下的 是 业务逻辑 了 。 哈
    uwp 嗯 我最近 准备开发一个 应用 。 嗯 走起
  • 原文地址:https://www.cnblogs.com/linkstar/p/7510409.html
Copyright © 2020-2023  润新知