ActiveMQ應用場景及應用實例總結

 本文主要對ActiveMQ應用場景及應用實例進行了總結,本文源碼已上傳github, 鏈接見文末。

ActiveMQ簡介

1.java消息服務:

 不同系統之間的信息交換,是我們開發中比較常見的場景,比如系統A要把數據發送給系統B,這個問題我們應該如何去處理? 1999年,原來的SUN公司領銜提出了一種面向消息的中間件服務–JMS規範(標準);常用的幾種信息交互技術(httpClient、hessian、dubbo、jms、webservice 五種).

2.JMS概述:

 JMS即Java消息服務(Java Message Service的簡稱),是Java EE 的標準/規範之一。這種規範(標準)指出:消息的發送應該是異步的、非阻塞的。也就是說消息的發送者發送完消息後就直接返回了,不需要等待接收者返回後才能返回,發送者和接收者可以說是互不影響。所以這種規範(標準)能夠減輕或消除系統瓶頸,實現系統之間去除耦合,提高系統的整體可伸縮性和靈活性。JMS只是Java EE中定義的一組標準API,它自身並不是一個消息服務系統,它是消息傳送服務的一個抽象,也就是說它定義了消息傳送的接口而並沒有具體實現。

3.ActiveMQ概述:

 JMS只是消息服務的一組規範和接口,並沒有具體的實現,而ActiveMQ就是JMS規範的具體實現;它是Apache下的一個項目,採用Java語言開發;是一款非常流行的開源消息服務器.
在這裏插入圖片描述

4.應用場景

(1)異步處理
 如下圖,用戶註冊後,直接響應,郵件和短信發送通過消息隊列異步處理。
在這裏插入圖片描述
 對比下圖,縮短了響應時間,增加了系統QPS
在這裏插入圖片描述

(2)應用解耦

 如下圖,應用消息隊列後,庫存系統不能正常使用,也不直接影響訂單系統。

  • 訂單系統:用戶下單後,訂單系統完成持久化處理,將消息寫入消息隊列,返回用戶訂單下單成功

  • 庫存系統:訂閱下單的消息,採用拉/推的方式,獲取下單信息,庫存系統根據下單信息,進行庫存操作
    在這裏插入圖片描述
     對比下圖:傳統模式下,庫存系統一斷無法正常使用,訂單系統也將無法正常使用。
    在這裏插入圖片描述

(3)流量消峯

 如下圖,一個典型應用場景:秒殺活動,一般會因爲流量過大,導致流量暴增,應用掛掉。爲解決這個問題,一般需要在應用前端加入消息隊列。這樣,用戶的請求,服務器接收後,首先寫入消息隊列。
在這裏插入圖片描述
這樣做有如下好處:

  • 可以控制活動的人數:假如消息隊列長度超過最大數量,則直接拋棄用戶請求或跳轉到錯誤頁面
  • 可以緩解短時間內高流量壓垮應用:秒殺業務根據消息隊列中的請求信息,再做後續處理

(4)其他場景
 其他的場景還有:日誌處理,消息通訊等。


ActiveMQ安裝配置

1.下載安裝

本文介紹Mac OS下安裝

(1)推薦方式:通過brew安裝ActiveMQ

$ brew install activemq

安裝完後,通過下列命令查看版本來確定是否安裝成功:

$activemq --version

在這裏插入圖片描述
(2)也可自行下載解壓安裝:
下載地址:http://activemq.apache.org/components/classic/download/
在這裏插入圖片描述
注意mac下自行解壓安裝後啓動方式是:

// 即所有命令要在 active安裝目錄/bin/macosx下執行
cd /usr/local/apache-activemq-5.15.9/bin/macosx
./activemq start

 

2.啓動activeMQ服務

activemq start

顯示:Running ActiveMQ Broker… 表示啓動成功

訪問地址:http://localhost:8161/admin/
默認賬號:admin / admin
默認端口:8161 (可自行修改/usr/local/apache-activemq-5.15.9/conf/jetty.xml)
在這裏插入圖片描述

3.ActiveMQ常用命令

Tasks:
    browse                   - Display selected messages in a specified destination.
    bstat                    - Performs a predefined query that displays useful statistics regarding the specified broker
    consumer                 - Receives messages from the broker
    create                   - Creates a runnable broker instance in the specified path.
    decrypt                  - Decrypts given text
    dstat                    - Performs a predefined query that displays useful tabular statistics regarding the specified destination type
    encrypt                  - Encrypts given text
    export                   - Exports a stopped brokers data files to an archive file
    list                     - Lists all available brokers in the specified JMX context
    producer                 - Sends messages to the broker
    purge                    - Delete selected destination's messages that matches the message selector
    query                    - Display selected broker component's attributes and statistics.
    start                    - Creates and starts a broker using a configuration file, or a broker URI.
    stop                     - Stops a running broker specified by the broker name.

Task Options (Options specific to each task):
    --extdir <dir>  - Add the jar files in the directory to the classpath.
    --version       - Display the version information.
    -h,-?,--help    - Display this help information. To display task specific help, use Main [task] -h,-?,--help

 更多:activemq官方命令行手冊


ActiveMQ之Hello World 實例

 不知從什麼時候起,漸漸習慣這種瞭解基本的理論後直接快速上手一個hello World實例~~ 不過,這確實是現學現用的一個好方法,但是有時間的話,還是覺得要看看書系統地瞭解一下,這樣,遇到了新問題,也有跡可循。

1.啓動activemq訪問:http://localhost:8161/admin/

點擊queues如圖:此時消息隊列爲空
在這裏插入圖片描述

2.新建maven項目

在這裏插入圖片描述
添加mq依賴:

<dependency>
			<groupId>org.apache.activemq</groupId>
			<artifactId>activemq-all</artifactId>
			<version>${activemq.version}</version>
</dependency>

最終pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.leon</groupId>
	<artifactId>activemq-helloworld</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>activemq-helloworld</name>
	<url>http://maven.apache.org</url>


	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<activemq.version>5.15.9</activemq.version>

	</properties>

	<dependencies>
		<!-- https://mvnrepository.com/artifact/org.apache.activemq/activemq-all -->
		<dependency>
			<groupId>org.apache.activemq</groupId>
			<artifactId>activemq-all</artifactId>
			<version>${activemq.version}</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>${java.version}</source>
					<target>${java.version}</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>


3.編寫消息生產者與消費者代碼

最終目錄結構如下:
在這裏插入圖片描述
(1)Const.java :常量類

package com.leon.activemq_helloworld;
/**常量類
 * 
 * @author leon
 *
 */
public interface Const {
	String MQ_DISTINATION_NAME = "mq_demo_queue";
}

(2)Producer.java:生產者

package com.leon.activemq_helloworld;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * 生產者
 * 
 * @author leon
 *
 */
public class Producer {
	public static void send(String msg, String distinationName) throws Exception {
		// 1、創建工廠連接對象,要指定ip和端口號(61616是默認的openwrite端口,在conf/activemq.xml裏配置)
		ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
		// 2、使用連接工廠創建一個連接對象
		Connection connection = connectionFactory.createConnection();
		// 3、開啓連接
		connection.start();
		// 4、使用連接對象創建會話(session)對象
		Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		// 5、使用會話對象創建目標對象,分爲queue(p2p:一對一)和topic(發佈訂閱:一對多)
		Queue queue = session.createQueue(distinationName);
		// 6、使用會話對象創建消息生產者對象
		MessageProducer producer = session.createProducer(queue);
		// 7、使用會話對象創建一個消息對象
		TextMessage textMessage = session.createTextMessage(msg);
		// 8、發送消息
		producer.send(textMessage);
		// 9、關閉資源
		producer.close();
		session.close();
		connection.close();
	}

	public static void main(String[] args) {
		try {
			send("hello world!", Const.MQ_DISTINATION_NAME);
			System.out.println("消息已發送");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

(3)Consumer.java:消費者

package com.leon.activemq_helloworld;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * 消費者
 * 
 * @author leon
 *
 */
public class Consumer {
	public static void cust(String distinationName) throws Exception {
		// 1、創建工廠連接對象,要指定ip和端口號(61616是默認的openwrite端口,在conf/activemq.xml裏配置)
		ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
		// 2、使用連接工廠創建一個連接對象
		Connection connection = connectionFactory.createConnection();
		// 3、開啓連接
		connection.start();
		// 4、使用連接對象創建會話(session)對象
		Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		// 5、使用會話對象創建目標對象,分爲queue(p2p:一對一)和topic(發佈訂閱:一對多)
		Queue queue = session.createQueue(distinationName);
		// 6、使用會話對象創建消費者對象
		MessageConsumer consumer = session.createConsumer(queue);
		// 7、向消費者對象中設置一個messageListener對象,用來監聽和接收消息
		consumer.setMessageListener(new MessageListener() {

			@Override
			public void onMessage(Message message) {
				// TODO Auto-generated method stub
				if (message instanceof TextMessage) {
					TextMessage textMessage = (TextMessage) message;
					try {
						System.out.println("接收到文本消息:");
						System.out.println(textMessage.getText());
					} catch (JMSException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		});
		// 8、保持程序等待接收消息
		System.in.read();
		// 9、關閉資源
		consumer.close();
		session.close();
		connection.close();
	}

	public static void main(String[] args) {
		try {
			cust(Const.MQ_DISTINATION_NAME);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

(4)模擬消息隊列p2p過程

a.執行Producer.java的main(): 生產者發佈消息 -> ActiveMQ消息隊列
訪問:http://localhost:8161/admin/ :點擊queues選項卡,發現新增了一條消息。
此時,未發送的消息:消費者數量:入隊:出隊 = 1:0:1:0
在這裏插入圖片描述
b.執行Consumer.java的main(): 消費者接收消息 <- ActiveMQ消息隊列
後臺打印:
在這裏插入圖片描述

訪問:http://localhost:8161/admin/ :點擊queues選項卡,發現新增了一位消費者,未發送消息減少了一條,出隊數量增加了1。
此時,未發送的消息:消費者數量:入隊:出隊 = 0:1:1:1

在這裏插入圖片描述

(5)模擬消息隊列發佈訂閱過程

同上,不過要先執行訂閱者代碼,再執行發佈者代碼,這樣訂閱者才能接受到發佈者發佈的第一條消息,詳情參考本文源碼:https://github.com/leon2016/activemq-helloworld.git

其實,就是將

Queue queue = session.createQueue(distinationName);

改爲

Topic topic = session.createTopic(distinationName);

\---- 未完待續----
TODO 總結activemq與spring整合應用實例。

源碼

本文源碼:
activemq-helloworld :https://github.com/leon2016/activemq-helloworld.git

參考文獻:

activemq官方命令行手冊
https://www.cnblogs.com/cyfonly/p/6380860.html
https://blog.csdn.net/qq_29963323/article/details/79728581
http://www.uml.org.cn/zjjs/201802111.asp

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