ActiveMQ详细入门,学不会来打我

上篇https://blog.csdn.net/weixin_43934104/article/details/107099424
说到消息中间件的一些基础和应对场景,现在我们直接来实际搞一把!


准备环境

首先大家要准备好我们的开发环境,建议大家下个Vmware Workstation ,自己搞个虚拟机玩其实挺香的。

  1. Linux系统 CentOS -7 x64 (可在VM中运行或者搞个服务器,把这个7版本的搭上去)
  2. 连接终端的Xshell (没有可以去下载一个,后续需要用这个里面的文件传输功能传压缩包)
  3. CentOS中先要有jdk (可通过java -version 查看是否有jdk 注意不要用openjdk 有的话就删掉(具体百度) 然后去官网下载jdk的linux的64位的文件并解压,配置环境变量,具体百度)
  4. 玩集群的可以下载安装好zookeeper,大家应该知道这玩意很得劲!

Xshell不知道怎么搞的可以看看我的这篇文章:https://blog.csdn.net/weixin_43934104/article/details/104265688

环境准备好了

  • 首先需要下载activemq的安装包:进入http://activemq.apache.org/
  • 然后下载经典版(ActiveMQ 5 “Classic”)就行并且选择Linux版本的tar.gz的下载
  • 用xshell的文件传输功能也就是xftp去把下载的这个压缩文件传到linux
  • 在终端里面输入: tar -xvf 文件压缩包名 可以解压下载的文件压缩包
  • mkdir /mq 创建我们的mq文件夹方便操作
  • mv apache-activemq-5.15.12/ mq 把压缩好的文件夹放到我们创建好的mq文件夹中
  • 进入activemq的文件,cd bin
  • 然后 ./activemq start 就可以启动activemq了
  • activemq的后台端口号为:61616 控制台的端口号:8161
  • 关闭防火墙 systemctl stop firewalld 我们测试可以关闭防火墙,正常的服务就是把这个端口号放到白名单,毕竟实际项目中防火墙不能随便关闭
  • 通过ifconfig查看你的Linux的网络地址,然后可以到浏览器输入:http://192.168.xxx.xxx:8161/就可以看到activemq的控制台界面了
    界面是这样的:
    在这里插入图片描述
    点击那个Manage 默认账户admin 密码 admin就可以登进去使用了
    在这里插入图片描述

安装好就要开始的重要部分

ActiveMQ通讯
首先就是JMS API:
在这里插入图片描述
这张老图很好的诠释了咱们的JMS API。
对于这个API我觉得可以学完后再来看比较容易理解和记忆,所以暂时不用深究。

两大模式特性

  1. 队列模型Queue(在点对点的消息传递域中,目的地被称为队列)
    在这里插入图片描述
  2. 主题模型Topic(在发布订阅消息传递域中,目的地被称为主题)
    在这里插入图片描述
    简单解释一下:
    队列的这种就是我发布消息到队列,然后你就从对列消费我的消息。类似两个人发短信。
    主题的这种就是我发布一大堆消息到一个容器,然后可以有很多人去订阅我,这样我发布的消息,订阅过我的人就可以接收消息。类似某音关注了别人就可以接收别人的发的动态这种意思。

消费情况

  • 先生产3条消息,启动1号消费者 —— 1号消费者会把3条消息全部消费

  • 先生产3条消息,先启动1号消费者,在启动2号消费者 —— 1号消费者消费了所有消息,2号消费者无法消费

  • 先打开两个消费者,再生产6条消息—两个消费者一人消费一半

其中,topic和queue的方式有所不同:topic必须先启动消费者,再启动生产者。

消费方式
既然说到消费,那有啥消费方式呢?

  1. 同步阻塞方式:receive()
    订阅者或消费者调用MessageConsumer的receive() 方法接收消息,receive() 方法能够接收到消息之前或超时之前将会一直阻塞
  2. 异步非阻塞方式:监听器onMessage()
    订阅者或消费者通过MessageConsumer的setMessageListener(MessageListener messageListener)方法注册一个消息监听器,当消息到达之后,系统自动调用监听器的onMessage(Message message) 方法。

上代码之前要知道我们利用Java使用ActiveMQ其实就是使用JMS开发
那我又要说一说JMS开发步骤啦!(重要内容来个红色的字!)
1. 创建一个ConnectionFactory
2. 通过ConnectionFactory去创建JMS Connection
3. 启动JMS Connection
4. 通过Connection 创建 Session
5. 通过Session 创建JMS Destination (Queue或Topic)
6. 创建MessageProducer或者创建JMS Message,并设置Destination
7. 创建MessageConsumer 或者注册一个JMS MessageListener
8. 发送或接收JMS Message
9. 关闭所有JMS资源

是不是有种JDBC的感觉?现在可以好好上代码了,另外,整个demo项目我也会想办法免费上传给大家参考。
我们先搞个demo,用idea新建个webApp项目,maven里面导个ActiveMQ的依赖,省事!
在这里插入图片描述
记得代码中所有的地址都要换上自己的
JmsProducer

import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
//提供服务者
public class JmsProducer {
//    步骤
//    创建连接工厂
//    通过连接工厂,获取连接Connection
//    创建 session
//    创建目的地
//    创建消息的生产者
//    发送消息到 mq 服务器
//    关闭资源

    //activemq连接地址,你们记得要换上自己的linux里面的地址
    public static final String ACTIVEMQ_URL = "tcp://192.168.239.128:61616";

    //队列名称
    public static final String QUEUE_NAME = "queue01";

    public static void main(String[] args) throws JMSException {

    //创建连接工厂
    //用户名和密码采用默认admin/admin
    ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);

    //通过连接工厂,获取连接Connection
    Connection connection = activeMQConnectionFactory.createConnection();

    //创建 session  第一个参数:事务  第二个参数:签收 AUTO_ACKNOWLEDGE 自动签收
        Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);

    //创建目的地
        Queue queue = session.createQueue(QUEUE_NAME);

    //创建消息的生产者
        MessageProducer messageProducer = session.createProducer(queue);
        //设置消息持久化,queue默认就是持久化
      //  messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);


        for (int i = 1; i <=3; i++) {
            //创建消息
            TextMessage textMessage = session.createTextMessage("message:"+i);
            //发送消息到 mq 服务器
            messageProducer.send(textMessage);
        }
        //关闭资源
        messageProducer.close();
        session.close();;
        connection.close();
    }

}

跑一把,然后到ActiveMQ那个页面去刷新,就可以看到创建了三条消息。
然后来个消费者JmsConsumer

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;
import java.io.IOException;

//消费消息者
public class JmsConsumer {
    //activemq连接地址
    public static final String ACTIVEMQ_URL = "tcp://192.168.239.128:61616";

    //队列名称
    public static final String QUEUE_NAME = "queue01";

    public static void main(String[] args) throws JMSException, IOException {

        //创建连接工厂
        //用户名和密码采用默认admin/admin
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);

        //通过连接工厂,获取连接Connection
        Connection connection = activeMQConnectionFactory.createConnection();
        //重点:一定要启动消费
        connection.start();

        //创建 session  第一个参数:事务  第二个参数:签收 AUTO_ACKNOWLEDGE 自动签收
        Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);

        //创建目的地
        Queue queue = session.createQueue(QUEUE_NAME);

        //创建消息的生产者
        MessageConsumer messageConsumer = session.createConsumer(queue);

        //消费消息
        //1 通过阻塞的方式 receive()  2  通过异步方式(监听方式)

        //阻塞的方式 receive() 同步阻塞
        while (true){
            TextMessage textMessage = (TextMessage) messageConsumer.receive(5000);//5秒没有消息出来,会自动断开连接
            if(textMessage !=null){
                System.out.println("消费消息:"+textMessage.getText());
            }else {
                break;
            }
        }
        //通过监听的方式(异步非阻塞方式)
        //监听器onMessage()
        messageConsumer.setMessageListener(message ->{
            //判断message不为空,并且类型是TextMessage的
            if(message != null && message instanceof TextMessage) {
                TextMessage textMessage = (TextMessage) message;
                if (textMessage != null) {
                    try {
                        System.out.println("消费消息:" + textMessage.getText());
                    } catch (JMSException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        //控制台不会关闭
        System.in.read();
        //关闭资源
        messageConsumer.close();
        session.close();;
        connection.close();
    }
}

启动跑一把,就可以看到消息被消费了,看不懂的去看看上面的那个图。
这是基于队列模式的生产和消费消息的例子。接下来就是基于主题模式的简单例子,可以对比一下,差别不是很大。
JmsProducer

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

/**
 * pub/sub 持久化模式:
 * 1.producer 设置持久化
 *
 * 2.consumer采用sub方式订阅消息
 */

//提供服务者
public class JmsProducer {
    //步骤
    //创建连接工厂
    //通过连接工厂,获取连接Connection
    //创建 session
    //创建目的地
    //创建消息的生产者
    //发送消息到 mq 服务器
    //关闭资源

    //activemq连接地址
    public static final String ACTIVEMQ_URL = "tcp://192.168.239.128:61616";

    //队列名称
    public static final String QUEUE_NAME = "topic01";

    public static void main(String[] args) throws JMSException {

        //创建连接工厂
        //用户名和密码采用默认admin/admin
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);

        //通过连接工厂,获取连接Connection
        Connection connection = activeMQConnectionFactory.createConnection();

        //创建 session  第一个参数:事务  第二个参数:签收 AUTO_ACKNOWLEDGE 自动签收
        Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);

        //创建目的地
        Topic topic = session.createTopic(QUEUE_NAME);

        //创建消息的生产者
        MessageProducer messageProducer = session.createProducer(topic);

        //设置持久化模式
        messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);

        for (int i = 1; i <=3; i++) {
            //创建消息
            TextMessage textMessage = session.createTextMessage("message:"+i);
            //发送消息到 mq 服务器
            messageProducer.send(textMessage);
        }
        //关闭资源
        messageProducer.close();
        session.close();;
        connection.close();
    }

}

JmsConsumer

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;
import java.io.IOException;

//消费消息者
public class JmsConsumer {
    //activemq连接地址
    public static final String ACTIVEMQ_URL = "tcp://192.168.239.128:61616";

    //队列名称
    public static final String TOPIC_NAME = "topic01";

    public static void main(String[] args) throws JMSException, IOException {

        //创建连接工厂
        //用户名和密码采用默认admin/admin
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);

        //通过连接工厂,获取连接Connection
        Connection connection = activeMQConnectionFactory.createConnection();

        //设置客户端ID
        connection.setClientID("ddc");


        //创建 session  第一个参数:事务  第二个参数:签收 AUTO_ACKNOWLEDGE 自动签收
        Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);

        //创建目的地
        Topic topic = session.createTopic(TOPIC_NAME);

        //订阅消息(消息是持久化)
        TopicSubscriber topicSubscriber = session.createDurableSubscriber(topic,"ddc");

        //重点:一定要启动消费
        connection.start();

        //创建消息的生产者
        MessageConsumer messageConsumer = session.createConsumer(topic);

        //接收消息


        //消费消息
        //1 通过阻塞的方式 receive()  2  通过异步方式(监听方式)

        //阻塞的方式 receive() 同步阻塞
        while (true){
            TextMessage textMessage = (TextMessage) messageConsumer.receive(5000);//5秒没有消息出来,会自动断开连接
            if(textMessage !=null){
                System.out.println("消费消息:"+textMessage.getText());
            }else {
                break;
            }
        }
        //通过监听的方式(异步非阻塞方式)
        //监听器onMessage()
        messageConsumer.setMessageListener(message ->{
            //判断message不为空,并且类型是TextMessage的
            if(message != null && message instanceof TextMessage) {
                TextMessage textMessage = (TextMessage) message;
                if (textMessage != null) {
                    try {
                        System.out.println("消费消息:" + textMessage.getText());
                    } catch (JMSException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        //控制台不会关闭
        System.in.read();

        //关闭资源
        messageConsumer.close();
        session.close();;
        connection.close();
    }
}

其中提一下,对于我们的JMS,是有持久化的功能,也就是服务器宕机后,消息依然存在,保证了JMS的可靠性。
只要使用messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);就使用了持久化机制。
不用持久化就是DeliveryMode.NON_PERSISTENT。
队列queue:默认是持久化传送模式。
主题Topic:生产者设置持久化传送模式,消费者使用订阅方式TopicSubscriber。

因为Topic采用的这种pub/sub持久化模式有的面试也会经常问,所以我也搞了个例子供大家学习:
同样的生产者:

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

/**
 * Topic模型(PUB/SUB)消息生产者
 *
 * topic 采用 pub/sub 持久化模式:
 *  1)producer 设置持久化
 *      messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);
 *  2)consumer 采用 sub 方式订阅消息
 *      connection.setClientID("hello");
 *      TopicSubscriber topicSubscriber = session.createDurableSubscriber(topic, "hello");
 */
public class JmsProducer {
    // activemq 连接 url
    public static final String ACTIVEMQ_URL = "tcp://192.168.0.101:61616";
    // 消息主题名
    public static final String TOPIC_NAME = "topic01";

    public static void main( String[] args ) throws JMSException {
        // 1. 创建连接工厂,按照给定的url,采用默认用户名和密码
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);

        // 2. 通过连接工厂,获取连接Connection
        Connection connection = activeMQConnectionFactory.createConnection();
        // 启动
        connection.start();

        // 3. 创建会话Session
        // 第一个参数:事务
        // 第二个参数:签收
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        // 4. 创建目的地 Destination
        // Destination 有两个实现:Queue、Topic
        Topic topic = session.createTopic(TOPIC_NAME);

        // 5. 创建消息生产者 MessageProducer
        MessageProducer messageProducer = session.createProducer(topic);
        // 设置持久化模式
        messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);

        // 发送3条消息到 mq
        for (int i = 1; i <= 3; i++) {
            // 6. 创建消息 Message
            TextMessage textMessage = session.createTextMessage("message " + i);
            // 7. 消息生产者发送消息到 mq 服务器
            messageProducer.send(textMessage);
        }

        // 8. 关闭资源
        messageProducer.close();
        session.close();
        connection.close();

        System.out.println("******消息发布到MQ完成");
    }
}

消费者

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

/**
 * Topic模型(PUB/SUB)消息消费者
 * 消费者
 *  Topic 的传递模式为持久化 persistent
 *      1) 一定要先运行一次消费者,等于向 MQ 注册,相当于订阅了这个主题,可以在 MQ 控制台的 Subscribers 查看
 *      2) 然后再运行生产者发送消息
 *      3) 此时无论消费者是否在线,都会接收到,若不在线,下次连接时,会把没有收过的消息都接收到
 */
public class JmsConsumer {
    // activemq 连接 url
    public static final String ACTIVEMQ_URL = "tcp://192.168.0.101:61616";
    // 消息主题名
    public static final String TOPIC_NAME = "topic01";

    public static void main(String[] args) throws JMSException {
        // 1. 创建连接工厂,按照给定的url,采用默认用户名和密码
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);

        // 2. 通过连接工厂,获取连接Connection
        Connection connection = activeMQConnectionFactory.createConnection();
        // 设置客户端 ID
        connection.setClientID("hello");

        // 3. 创建会话Session
        // 第一个参数:事务
        // 第二个参数:签收
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        // 4. 创建目的地 Destination
        // Destination 有两个实现:Queue、Topic
        Topic topic = session.createTopic(TOPIC_NAME);

        // 5. 订阅消息,(消息是持久化)
        TopicSubscriber topicSubscriber = session.createDurableSubscriber(topic, "mq2");
        // 启动
        connection.start();

        // 6. 接收消息
        Message message = topicSubscriber.receive();
        while (null != message) {
            TextMessage textMessage = (TextMessage)message;
            System.out.println("******消费者消费消息: " + textMessage.getText());

            message = topicSubscriber.receive();
        }

        // 7. 关闭资源
        session.close();
        connection.close();
    }
}

对比Queue和Topic的不同

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

  • Topic是可以重复消费的,消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。
    它和点对点方式不同,发布到topic的消息会被所有订阅者消费。
    当生产者发布消息,不管是否有消费者。都不会保存消息。相当于一个广播。
    在这里插入图片描述
    到这ActiveMQ的通讯讲的其实差不多了,不过关于JMS的可靠性不止持久化这一个,还有事务,签收机制,所以学到这,我们可以说入门啦!


大家可以看到我整篇都在搞JMS,它在我们使用mq来说是非常重要的,我们这里的那么多开发步骤,在以后用到的spring整合后,就还是很简单的,不用写那么多步骤代码。
有时间小二会把JMS Message详细给大家讲讲,然后还有Broker,以及一些细节知识,记得关注我喔!


代码文件目录,已上传
https://download.csdn.net/download/weixin_43934104/12573795

在这里插入图片描述
实 践 出 真 知!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值