一起學習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
    在這裏插入圖片描述
  • 解壓 ,eg: E:\software\apache-activemq-5.15.9
    在這裏插入圖片描述
    解壓後如上圖所示,
    bin 目錄:系統jar包和一些啓動腳本文件
    conf 目錄:系統配置文件夾,包含mq配置,web console配置,用戶組等配置
    data 目錄:數據倉庫文件夾,主要存儲一些系統日誌文件和持久化的kahadb數據文件。
    webapps 目錄:web console應用
  • 運行
  1. 進入 bin 目錄
    在這裏插入圖片描述
  2. 選擇對應的操作系統位數文件夾,我的是64位
    在這裏插入圖片描述

點擊運行activemq.bat
或者
在cmd控制檯運行 命令

cd [activemq_install_dir]
bin\ activemq start

比如我的安裝路徑是E:\software\apache-activemq-5.15.9\bin\win64
在這裏插入圖片描述
如果以管理員身份運行: InstallService.bat則會安裝服務,如下圖所示:
在這裏插入圖片描述
可以將服務設置爲自動啓動,當操作系統運行的時候自動啓動服務,就無需運行activemq.bat或者執行 activemq start命令。

  1. 出現如下圖所示則運行成功
    在這裏插入圖片描述
  2. 訪問console頁面 http://localhost:8161,出現如下圖界面則表示安裝成功
    在這裏插入圖片描述

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

<dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-all</artifactId>
            <version>5.15.9</version>
        </dependency>

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隊列已經有一個消息
在這裏插入圖片描述

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,
在這裏插入圖片描述

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
在這裏插入圖片描述

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章