消息中间件之ActiveMQ

一、关于中间件

(1)什么是中间件

  • 非底层操作系统软件,非业务应用软件,不是直接给最终用户使用的,不能直接给客户带来价值的软件统称为中间件
  • 关注于数据的发送和接收,利用高效可靠的异步消息传递机制集成分布式系统。

(2)消息中间件有什么好处

 

简单来说,使用中间件最主要的好处有三点

  • 解耦
  • 异步
  • 横向扩展、使用较为灵活

 

(3)内容扩展JMS和AMQP

提到消息中间件,这里有两个名词需要了解下,就是JMS和AMQP

什么是JMS?

JMS(Java MessageService)实际上是指JMS API。JMS是由Sun公司早期提出的消息标准,旨在为java应用提供统一的消息操作,包括create、send、receive 等。JMS已经成为Java Enterprise Edition的一部分。从使用角度看,JMS和JDBC担任差不多的角色,用户都是根据相应的接口可以和实现了JMS的服务进行通信,进行相关的操作。

什么是AMQP?

AMQP是一种协议,更准确的说是一种binary wire-level protocol(链接协议)。这是其和JMS的本质差别,AMQP不从API层进行限定,而是直接定义网络交换的数据格式。这使得实现了AMQP的provider天然性就是跨平台的。意味着我们可以使用Java的AMQP provider,同时使用一个python的producer加一个rubby的consumer。从这一点看,AQMP可以用http来进行类比,不关心实现的语言,只要大家都按照相应的数据格式去发送报文请求,不同语言的client均可以和不同语言的server链接。

目前AMQP逐渐成为消息队列的一个标准协议,当前比较流行的rabbitmq、stormmq都使用了AMQP实现。

     最后将JMS和AMQP的各项对比如下:

JMS

AMQP

定义

Java api

Wire-protocol

跨语言

跨平台

Model

提供两种消息模型:

(1)、Peer-2-Peer

(2)、Pub/sub

提供了五种消息模型:

(1)、direct exchange

(2)、fanout exchange

(3)、topic change

(4)、headers exchange

(5)、system exchange

本质来讲,后四种和JMS的pub/sub模型没有太大差别,仅是在路由机制上做了更详细的划分;

支持消息类型

多种消息类型:

TextMessage

MapMessage

BytesMessage

StreamMessage

ObjectMessage

Message (只有消息头和属性)

byte[]

当实际应用时,有复杂的消息,可以将消息序列化后发送。

综合评价

JMS 定义了JAVA API层面的标准;在java体系中,多个client均可以通过JMS进行交互,不需要应用修改代码,但是其对跨平台的支持较差;

AMQP定义了wire-level层的协议标准;天然具有跨平台、跨语言特性。

 

二、常用的中间件对比

  • ActiveMQ

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

  • RabbitMQ

RabbitMQ是一个开源的AMQP实现,服务端采用Erlang语言编写。用于分布式系统中的存储消息转发,在易用性、扩展性、高可用性等方面表现不俗

  • Kafka

Kafka是一种高吞吐量的分布式发布订阅消息系统,是一个分布式的、分区的、可靠的的分布式日志储存系统。他通过一种独特的设计提供了一个消息系统的功能

接下来我们对比一下这三种消息中间件的优劣及综合评级如下图

 

三、JMS规范讲解

(1)JMS规范详解

既然我们本文主要讲解ActiveMQ,那先在这说一下JMS规范,毕竟他是基于JMS实现的,先说一下JMS的相关概念:

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

上面提到了JMS实现消息队列有两种模式,接下来就讲解下这两种模式的区别

(2)JSM消息模式

队列模式

  • 客户端包括生产者和消费者
  • 队列中的消息只能被一个消费者消费
  • 消费者可以随时消费队列中的消息

主题模式

  • 客户端包括发布者和订阅者
  • 主题中的消息被所有订阅者消费
  • 消费者不能消费订阅之前就发布的消息

 

 

三、使用ActiveMQ实现JMS的两种消息模式

(1)环境搭建

理论部分我们已经讲解完了,现在需要实现两种消息模式,首先我们准备消息服务器环境

  • 首先下载消息服务器ActiveMQ

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

  • 接下来准备开发工具,我这里用的是win10环境下的idea

(2)实现队列消息模式

1、打开idea新建一个普通的Maven项目

2、填写项目信息

 

3、项目新建完成后我们先来了解下这几个常用的对象

 

4、开始编码,新建一个queue包,在包下创建AppProducer类(消息生产者),具体代码如下:

很简单,就是创建一个消息生产者,循环发送消息

package vip.ablog.jms.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class AppProducer {
    private static final String url = "tcp://127.0.0.1:61616";
    private static final String queueName = "queue-test";
    public static void main(String[] args) throws JMSException {
            Connection connection = null;
            //1、创建connectionFactory连接工厂
            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(queueName);
            //6、创建生产者
            MessageProducer producer = session.createProducer(destination);
            //7、开始发送消息
            for (int i = 0; i < 100; i++) {
                //创建消息
                TextMessage msg = session.createTextMessage("test:" + i);
                //发布消息
                producer.send(msg);
                System.out.println("发送消息:" + msg.getText());
            }
            connection.close();
    }
}

 

6、生产者创建后接下来我们在queue包下创建AppConsumer类(消息的消费者),以接收生产者发送的消息,具体代码如下:

package vip.ablog.jms.queue;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;
/***
 * 消息的消费者
 */
public class AppConsumer {
    private static final String url = "tcp://127.0.0.1:61616";
    private static final String queueName = "queue-test";
    public static void main(String[] args) throws JMSException {
        Connection connection = null;
        //1、创建connectionFactory连接工厂
        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(queueName);
        //6、创建消费者
        MessageConsumer consumer = session.createConsumer(destination);
        //创建一个监听器
        consumer.setMessageListener(new MessageListener() {
            public void onMessage(Message message) {
                try {
                    System.out.println("接收到消息:"+((TextMessage) message).getText());
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        });

        //connection.close();
    }
}

7、接下来代码我们就写完了,可以发现这两个类是包含mian方法的,先不用管他,接下来然我们配置刚刚下载好的ActiveMQ,下载完成后解压即可使用,目录结构如下:

我们进入bin目录下,进入对应系统位数的目录下,运行activemq.bat文件,不要关闭窗口

8、运行后,在浏览器输入下面地址,用户名密码默认都是admin,即可进入ActiveMQ的后台管理系统

9、现在我们进入idea 运行我们的消息发布者AppProducer,运行后进入Queue队列菜单即可看到我们发送的消息

 

10、现在我们运行AppConsumer类,来消费接受这些消息,运行后会在控制台打印消息内容,接下来我们进入管理页面会看到,之前消息队列中等待的消息已经被消费

 

(3)实现主题消息模式

1、现在我们新建topic包,在包下新建AppProducer和AppConsumer类,来创建订阅者和消费者,具体代码如下:

AppProducer.java

package vip.ablog.jms.topic;


import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

public class AppProducer {
    private static final String url = "tcp://127.0.0.1:61616";
    private static final String topicame = "topic-test";

    public static void main(String[] args) throws JMSException {
            Connection connection = null;
            //1、创建connectionFactory连接工厂
            ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
            //2、创建Connection
            connection = connectionFactory.createConnection();
            //3、启动连接
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            //5、创建一个目标
            Destination destination = session.createTopic(topicame);
            //6、创建生产者
            MessageProducer producer = session.createProducer(destination);
            //7、开始发送消息
            for (int i = 0; i < 100; i++) {
                //创建消息
                TextMessage msg = session.createTextMessage("test:" + i);
                //发布消息
                producer.send(msg);
                System.out.println("发送消息:" + msg.getText());
            }
            connection.close();


    }
}

AppConsumer.java

package vip.ablog.jms.topic;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

/***
 * 消息的消费者
 */
public class AppConsumer {
    private static final String url = "tcp://127.0.0.1:61616";
    private static final String topicName = "topic-test";

    public static void main(String[] args) throws JMSException {
        Connection connection = null;
        //1、创建connectionFactory连接工厂
        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(topicName);
        //6、创建消费者
        MessageConsumer consumer = session.createConsumer(destination);
        //创建一个监听器
        consumer.setMessageListener(new MessageListener() {
            public void onMessage(Message message) {
                TextMessage msg = (TextMessage) message;
                try {
                    System.out.println("接收到消息:"+((TextMessage) message).getText());
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        });

        //connection.close();


    }
}

接下来我们我们像上面队列模式一样运行:

 首先运行AppProducer消息发布者,发送100条消息

 然后运行AppConsumer消息订阅者,

然后你会惊奇的发现,毛都没收到,哈哈

没收到就对了!

上面我们提到过,在主题模式下,我们不能接收未订阅之前的消息

换言之,就是说我发消息时你订阅者也要在运行,不然肯定收不到,没订阅要啥自行车!

还有:上面还提到过队列模式和主题模式的区别,这个由于篇幅问题先不讲解了,你们自己实践下就行,就是在主题模式和队列模式下开启多个消息的消费者,然后发送消息就会看到他俩的另一个区别!

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值