一起学习ActiveMQ (一) ActiveMQ入门

一起学习ActiveMQ (一) ActiveMQ入门

Apache ActiveMQ™是最流行的开源,多协议,基于Java的消息服务器。它支持行业标准协议,因此用户可以通过广泛的语言和平台获得客户选择的好处。可以使用C,C ++,Python,.Net等连接。使用无处不在的AMQP协议集成您的多平台应用程序。

1. 安装ActiveMQ

在官网下载最新的ActiveMQ http://activemq.apache.org/components/classic/download/

1.1 Windows安装:

  • 下载 apache-activemq-5.15.9-bin.zip
    一起学习ActiveMQ (一) ActiveMQ入门_第1张图片
  • 解压 ,eg: E:\software\apache-activemq-5.15.9
    一起学习ActiveMQ (一) ActiveMQ入门_第2张图片
    解压后如上图所示,
    bin 目录:系统jar包和一些启动脚本文件
    conf 目录:系统配置文件夹,包含mq配置,web console配置,用户组等配置
    data 目录:数据仓库文件夹,主要存储一些系统日志文件和持久化的kahadb数据文件。
    webapps 目录:web console应用
  • 运行
  1. 进入 bin 目录
    一起学习ActiveMQ (一) ActiveMQ入门_第3张图片
  2. 选择对应的操作系统位数文件夹,我的是64位
    一起学习ActiveMQ (一) ActiveMQ入门_第4张图片

点击运行activemq.bat
或者
在cmd控制台运行 命令

cd [activemq_install_dir]
bin\ activemq start

比如我的安装路径是E:\software\apache-activemq-5.15.9\bin\win64
在这里插入图片描述
如果以管理员身份运行: InstallService.bat则会安装服务,如下图所示:
一起学习ActiveMQ (一) ActiveMQ入门_第5张图片
可以将服务设置为自动启动,当操作系统运行的时候自动启动服务,就无需运行activemq.bat或者执行 activemq start命令。

  1. 出现如下图所示则运行成功
    一起学习ActiveMQ (一) ActiveMQ入门_第6张图片
  2. 访问console页面 http://localhost:8161,出现如下图界面则表示安装成功
    一起学习ActiveMQ (一) ActiveMQ入门_第7张图片

1.2 Unix安装

与windows安装并无太大差异。
从命令shell,切换到安装目录并ActiveMQ作为foregroud进程运行:

cd [activemq_install_dir]/bin
./activemq console

从命令shell,切换到安装目录并ActiveMQ作为daemon进程运行:

cd [activemq_install_dir]/bin
./activemq start

2. 使用Java代码访问ActiveMQ

ActiveMQ实现了JMS,JMS中的一些关键接口如下:

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

2.1 引入pom


            org.apache.activemq
            activemq-all
            5.15.9
        

2.2 编写Queue模式生产者代码

利用如下代码将消息发送到TEST.FOO队列

// Create a ConnectionFactory
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("failover:(tcp://localhost:61616)?initialReconnectDelay=100");

// Create a Connection
Connection connection = connectionFactory.createConnection();
connection.start();

// Create a Session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

// Create the destination (Topic or Queue)
Destination destination = session.createQueue("TEST.FOO");

// Create a MessageProducer from the Session to the Topic or Queue
MessageProducer producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

// Create a messages
String text = "Hello world! From: " + Thread.currentThread().getName() + " : " + this.hashCode();
TextMessage message = session.createTextMessage(text);

// Tell the producer to send the message
System.out.println("Sent message: "+ message.hashCode() + " : " + Thread.currentThread().getName());
producer.send(message);

// Clean up
session.close();
connection.close();

输出日志:

INFO | Successfully connected to tcp://localhost:61616
Sent message: 901950302 : Thread-0

在console的queues解密查看,TEST.FOO队列已经有一个消息
一起学习ActiveMQ (一) ActiveMQ入门_第8张图片

2.3 编写Queue模式消费者代码

编写如下消费者代码

// Create a ConnectionFactory
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");

// Create a Connection
Connection connection = connectionFactory.createConnection();
connection.start();

connection.setExceptionListener(this);

// Create a Session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

// Create the destination (Topic or Queue)
Destination destination = session.createQueue("TEST.FOO");

// Create a MessageConsumer from the Session to the Topic or Queue
MessageConsumer consumer = session.createConsumer(destination);

// Wait for a message
Message message = consumer.receive(1000);

if (message instanceof TextMessage) {
	TextMessage textMessage = (TextMessage) message;
	String text = textMessage.getText();
	System.out.println("Received: " + text);
} else {
	System.out.println("Received: " + message);
}

consumer.close();
session.close();
connection.close();

输出日志:

Received: Hello world! From: Thread-0 : 1989096651

在console的queues解密查看,TEST.FOO队列已经有一个消息被消费,且队列当前消息数量为0,
一起学习ActiveMQ (一) ActiveMQ入门_第9张图片

2.4 编写topic模式生产者代码

与Queue模式类似只需将:

Destination destination = session.createQueue("TEST.FOO");

改为

Destination destination = session.createTopic("TEST.FOO");

运行,日志输出如下:

INFO | Successfully connected to tcp://localhost:61616
Sent message: 1597511522 : Thread-0

console界面选择topics
一起学习ActiveMQ (一) ActiveMQ入门_第10张图片

2.5 编写topic模式消费者代码

为了演示topic,需要启动多个线程,更改后的代码如下:

public class Consumer {
    public static void main(String[] args) {
        thread(new HelloWorldConsumer(), false);
        thread(new HelloWorldConsumer(), false);
        thread(new HelloWorldConsumer(), false);
    }

    public static void thread(Runnable runnable, boolean daemon) {
        Thread brokerThread = new Thread(runnable);
        brokerThread.setDaemon(daemon);
        brokerThread.start();
    }

    public static class HelloWorldConsumer implements Runnable, ExceptionListener {
        public void run() {
            try {

                // Create a ConnectionFactory
                ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");

                // Create a Connection
                Connection connection = connectionFactory.createConnection();
                connection.start();

                connection.setExceptionListener(this);

                // Create a Session
                Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

                // Create the destination (Topic or Queue)
                Destination destination = session.createTopic("TEST.FOO");

                // Create a MessageConsumer from the Session to the Topic or Queue
                MessageConsumer consumer = session.createConsumer(destination);

                // Wait for a message
                Message message = consumer.receive(1000);

                while (null == message) {
                    Thread.sleep(100);
                    message = consumer.receive(1000);
                }
                if (message instanceof TextMessage) {
                    TextMessage textMessage = (TextMessage) message;
                    String text = textMessage.getText();
                    System.out.println("Received: " + text);
                } else {
                    System.out.println("Received: " + message);
                }

                consumer.close();
                session.close();
                connection.close();
            } catch (Exception e) {
                System.out.println("Caught: " + e);
                e.printStackTrace();
            }
        }

        public synchronized void onException(JMSException ex) {
            System.out.println("JMS Exception occured.  Shutting down client.");
        }
    }
}

启动2个线程,运行后发现一直没有消费消息,但是在console界面发现队列里面是有消息没有被消费的,这是怎么回事呢?
原来:主题模式下,如果消费者是在生产者产生消息之后来的,那么是不会对之前的消息进行消费的

现在重新先运行consumer:
在这里插入图片描述
此时发现队列消费者数量为3,现在重新发送一条消息,在consumer客户端日志如下:

Received: Hello world! From: Thread-0 : 691909443
Received: Hello world! From: Thread-0 : 691909443
Received: Hello world! From: Thread-0 : 691909443

且消费的消息数量变为3条
在这里插入图片描述
同时我们发现,主题模式下,所有消费者都会消费同一个消息,也就是消息以广播的形式发送给每一个消费者

下章我们将使用spring boot进行消息的发送与消费
end

你可能感兴趣的:(MQ)