ActiveMQ——基礎知識與模擬體驗
最近在學習一個Java的開源專案,git地址:https://gitee.com/shuzheng/zheng
該開源專案開發環境需具備ActiveMQ,所以特地學習一下ActiveMQ。
一、ActiveMQ是什麼?
1)JMS概述
JMS即Java訊息服務(Java Message Service的簡稱),是Java EE 的標準/規範之一。這種規範(標準)指出:訊息的傳送應該是非同步的、非阻塞的。也就是說訊息的傳送者傳送完訊息後就直接返回了,不需要等待接收者返回後才能返回,傳送者和接收者可以說是互不影響。所以這種規範(標準)能夠減輕或消除系統瓶頸,實現系統之間去除耦合,提高系統的整體可伸縮性和靈活性。JMS只是Java EE中定義的一組標準API,它自身並不是一個訊息服務系統,它是訊息傳送服務的一個抽象,也就是說它定義了訊息傳送的介面而並沒有具體實現。
2)ActiveMQ概述
ActiveMQ就是JMS規範的具體實現;它是Apache下的一個專案,採用Java語言開發,是一款非常流行的開源訊息伺服器(訊息佇列中介軟體)
3)ActiveMQ與JMS關係
JMS只是定義了一組有關訊息傳送的規範和標準,並沒有真正實現,也就說JMS只是定義了一組介面;其具體實現由不同的訊息中介軟體廠商提供,比如Apache ActiveMQ就是JMS規範的具體實現,Apache ActiveMQ才是一個訊息服務系統,而JMS不是。
訊息佇列中介軟體是分散式系統中重要的元件,主要解決應用耦合,非同步訊息,流量削鋒等問題。實現高效能,高可用,可伸縮和最終一致性架構。是大型分散式系統不可缺少的中介軟體。目前在生產環境,使用較多的訊息佇列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ等。
二、應用場景——非同步處理,應用解耦,流量削鋒和訊息通訊
2.1非同步處理
場景說明:使用者註冊後,需要發註冊郵件和註冊簡訊。
傳統的做法:1.序列的方式; 2.並行方式。
1)序列方式:將註冊資訊寫入資料庫成功後,傳送註冊郵件,再傳送註冊簡訊。以上三個任務全部完成後,返回給客戶端。
2)並行方式:將註冊資訊寫入資料庫成功後,傳送註冊郵件的同時,傳送註冊簡訊。以上三個任務完成後,返回給客戶端。
與序列的差別是,並行的方式可以提高處理的時間。引入訊息佇列,就可以將不是必須的業務邏輯改為非同步處理。
2.2應用解耦
場景說明:使用者下單後,訂單系統需要通知庫存系統。傳統的做法是,訂單系統呼叫庫存系統的介面。這種模式存在如下缺點:
1) 假如庫存系統無法訪問,則訂單減庫存將失敗,從而導致訂單失敗;
2) 訂單系統與庫存系統耦合;
引入應用訊息佇列後的方案:
1)訂單系統:使用者下單後,訂單系統完成持久化處理,將訊息寫入訊息佇列,返回使用者訂單下單成功。
2)庫存系統:訂閱下單的訊息,採用拉/推的方式,獲取下單資訊,庫存系統根據下單資訊,進行庫存操作。
假如:在下單時庫存系統不能正常使用。也不影響正常下單,因為下單後,訂單系統寫入訊息佇列就不再關心其他的後續操作了。實現訂單系統與庫存系統的應用解耦。
2.3流量削鋒
流量削鋒也是訊息佇列中的常用場景,一般在秒殺或團搶活動中使用廣泛。
應用場景:秒殺活動,一般會因為流量過大,導致流量暴增,應用掛掉。為解決這個問題,一般需要在應用前端加入訊息佇列。
可以控制活動的人數;
可以緩解短時間內高流量壓垮應用;
使用者的請求,伺服器接收後,首先寫入訊息佇列。假如訊息佇列長度超過最大數量,則直接拋棄使用者請求或跳轉到錯誤頁面;
秒殺業務根據訊息佇列中的請求資訊,再做後續處理。
2.4日誌處理
日誌處理是指將訊息佇列用在日誌處理中,比如Kafka的應用,解決大量日誌傳輸的問題。
日誌採集客戶端,負責日誌資料採集,定時寫受寫入Kafka佇列;
Kafka訊息佇列,負責日誌資料的接收,儲存和轉發;
日誌處理應用:訂閱並消費kafka佇列中的日誌資料;
二.ActiveMQ的使用
1、JMS兩種訊息傳送模式
1)點對點( Point-to-Point):專門用於使用佇列Queue傳送訊息;基於佇列Queue的點對點訊息只能被一個消費者消費,如多個消費者都註冊到同一個訊息佇列上,當生產者傳送一條訊息後,而只有其中一個消費者會接收到該訊息,而不是所有消費者都能接收到該訊息。
2)釋出/訂閱(Publish/Subscribe):專門用於使用主題Topic傳送訊息。基於主題的釋出與訂閱訊息能被多個消費者消費,生產者傳送的訊息,所有訂閱了該topic的消費者都能接收到。
2、 JMS API可以分為3個主要部分:
1)公共API:可用於向一個佇列或主題傳送訊息或從其中接收訊息;
2)點對點API:專門用於使用佇列Queue傳送訊息;
3)釋出/訂閱API:專門用於使用主題Topic傳送訊息。
JMS公共API:
在JMS公共API內部,和傳送與接收訊息有關的JMS API介面主要是:ConnectionFactory/Connection/Session/Message/Destination/MessageProducer/MessageConsumer 。它們的關係是:一旦有了ConnectionFactory,就可以建立Connection,一旦有了Connection,就可以建立Session,而一旦有了Session,就可以建立Message、MessageProducer和MessageConsumer。
JMS點對點API:
點對點(p2p)訊息傳送模型API是指JMS API之內基於佇列(Queue)的介面:QueueConnectionFactory/QueueConnection/QueueSession/Message/Queue/QueueSender/QueueReceiver. 從介面的命名可以看出,大多數介面名稱僅僅是在公共API介面名稱之前新增Queue一詞。一般來說,使用點對點訊息傳送模型的應用程式將使用基於佇列的API,而不使用公共API 。
JMS釋出/訂閱API:
釋出/訂閱訊息傳送模型API是指JMS API之內基於主題(Topic)的介面:TopicConnectionFactory/TopicConnection/TopicSession/Message/Topic/TopicPublisher/TopicSubscriber. 由於基於主題(Topic)的JMS API類似於基於佇列(Queue)的API,因此在大多數情況下,Queue這個詞會由Topic取代。
3、ActiveMQ的下載與安裝
1)直接去官網(http://activemq.apache.org/)下載最新版本即可,由於這是免安裝的,只需要解壓就行了。安裝完之後進入bin目錄,雙擊 activemq.bat檔案(linux下在bin目錄下執行 activemq start)
2)訪問控制檯(檢驗是否成功)
在瀏覽器輸入:http://ip:8161/admin/ 會彈出登陸框,賬號和密碼都是預設admin。
3)修改埠號
61616為對外服務埠號
8161為控制器埠號
當埠號衝突時,可以修改這兩個埠號。cd conf ,修改activemq.xml 修改裡面的61616埠。修改jetty.xml,修改裡面的8161埠。
4)刪除不活動佇列
一般情況下,ActiveMQ的queue或者topic在不使用之後,可以通過web控制檯來刪除掉。當然,也可以通過配置,使得broker可以自動探測到無用的佇列(一定時間內為空的佇列)並刪除掉,回收響應資源。
activemq.xml
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.base}/data" destroyApplicationContextOnStop="true" schedulePeriodForDestinationPurge="10000">
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry topic=">" gcInactiveDestinations="true" inactiveTimoutBeforeGC="100000" memoryLimit="1mb">
<pendingSubscriberPolicy>
<vmCursor />
</pendingSubscriberPolicy>
</policyEntry>
<policyEntry queue=">" gcInactiveDestinations="true" inactiveTimoutBeforeGC="100000" memoryLimit="1mb">
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>
</broker>
schedulePeriodForDestinationPurge:10000 每十秒檢查一次,預設為0,此功能關閉
gcInactiveDestinations: true 刪除掉不活動佇列,預設為false
inactiveTimoutBeforeGC:30000 不活動30秒後刪除,預設為60秒
PS:對於topic的不活動佇列只是,10秒中之類沒有消費者進行註冊監聽,如果一個使用者事先註冊了這個監聽,但是他一直沒有登入,那麼這算活動佇列。而queue只要有訊息沒有出佇列就表示活動佇列。
附:訊息中介軟體的用途和優點
1)將資料從一個應用程式傳送到另一個應用程式,或者從軟體的一個模組傳送到另外一個模組;
2)負責建立網路通訊的通道,進行資料的可靠傳送;
3)保證資料不重發,不丟失;
4)能夠實現跨平臺操作,能夠為不同作業系統上的軟體整合技工資料傳送服務
三、模擬HelloWord體驗ActiveMQ
下載MQ以後,要將---bin.zip解壓縮后里面的activemq-all-5.11.1.jar包加入到classpath下面,這個包包含了所有jms介面api的實現,專案結構圖:
啟動MQ,啟動成功,開啟該連結:http://localhost:8161/admin/
賬號和密碼都是admin,啟動成功後,圖如下:
生產者和消費者程式碼如下:
package com.activemq;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
/**
* 生產者(訊息傳送者)
* @author admin
*
*/
public class JMSProducer {
// 賬號(預設連線使用者名稱)
private static final String user = ActiveMQConnection.DEFAULT_USER;
// 密碼
private static final String pwd = ActiveMQConnection.DEFAULT_PASSWORD;
// 地址
private static final String url = ActiveMQConnection.DEFAULT_BROKER_URL;
private static final int sendnum = 10;
public static void main(String[] args) {
// 連線工廠
ConnectionFactory connectionFactory;
// 連線
Connection connection = null;
// 會話
Session session;
// 訊息目的
Destination destination;
// 訊息生產者
MessageProducer messageProducer;
// 例項化工廠
connectionFactory = new ActiveMQConnectionFactory(JMSProducer.user, JMSProducer.pwd, JMSProducer.url);
try {
connection = connectionFactory.createConnection();
connection.start();
session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
destination = session.createQueue("HelloWord");
messageProducer = session.createProducer(destination);
sendMessage(session, messageProducer);
session.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 傳送訊息
* @param session
* @param messageProducer 訊息生產者
* @throws Exception
*/
public static void sendMessage(Session session, MessageProducer messageProducer) throws Exception {
for (int i = 0; i < 10; i++) {
TextMessage message = session.createTextMessage("ActiveMQ" + i);
System.out.println("傳送訊息" + i);
messageProducer.send(message);
}
}
}
package com.activemq;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
/**
* 消費者(訊息接收者)
* @author admin
*
*/
public class JMSConsumer {
private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;// 預設連線使用者名稱
private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;// 預設連線密碼
private static final String BROKEURL = ActiveMQConnection.DEFAULT_BROKER_URL;// 預設連線地址
public static void main(String[] args) {
ConnectionFactory connectionFactory;// 連線工廠
Connection connection = null;// 連線
Session session;// 會話 接受或者傳送訊息的執行緒
Destination destination;// 訊息的目的地
MessageConsumer messageConsumer;// 訊息的消費者
// 例項化連線工廠
connectionFactory = new ActiveMQConnectionFactory(JMSConsumer.USERNAME, JMSConsumer.PASSWORD,
JMSConsumer.BROKEURL);
try {
// 通過連線工廠獲取連線
connection = connectionFactory.createConnection();
// 啟動連線
connection.start();
// 建立session
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 建立一個連線HelloWorld的訊息佇列
destination = session.createQueue("HelloWord");
// 建立訊息消費者
messageConsumer = session.createConsumer(destination);
while (true) {
TextMessage textMessage = (TextMessage) messageConsumer.receive(100000);
if (textMessage != null) {
System.out.println("收到的訊息:" + textMessage.getText());
} else {
break;
}
}
} catch (JMSException e) {
e.printStackTrace();
}
}
}
啟動生產者,輸出如下:
然後看一下ActiveMQ伺服器,Queues內容如下:
我們可以看到建立了一個名稱為HelloWorld的訊息佇列,佇列中有10條訊息未被消費,我們也可以通過Browse檢視是哪些訊息:
這些佇列中的訊息,被刪除,消費者則無法消費,接下來,執行一下消費者:
現在我們再看一下ActiveMQ伺服器,Queues內容如下:
我們可以看到HelloWorld的訊息佇列發生變化,多一個訊息者,佇列中的10條訊息被消費了,點選Browse檢視,已經為空了。
點選Active Consumers,我們可以看到這個消費者的詳細資訊。
相關文章
- flutter初體驗之基礎控制元件知識Flutter控制元件
- Cookie 與 Session 基礎知識CookieSession
- VCS基礎知識與概念
- IO基礎知識與概念
- Java基礎知識_記憶體Java記憶體
- 軟體測試基礎知識
- node記憶體基礎知識記憶體
- 報表軟體基礎知識
- 知識乾貨:基礎儲存服務新手體驗營
- JAVA與tomcat基礎知識JavaTomcat
- 嵌入式基礎(2)---硬體基礎知識
- 基礎知識
- 虛擬化學習筆記-基礎知識筆記
- 效能測試基礎知識體系
- 伺服器虛擬化基礎知識:如何虛擬化?伺服器
- Linux基本知識與基礎命令Linux
- Python知識體系-Python2基礎知識Python
- 資訊處理技術基礎知識(2.4多媒體基礎知識 )--第2章
- 大規模C++程式設計 -- 基礎知識C++程式設計
- AI 基礎知識AI
- Webpack 基礎知識Web
- Dart基礎知識Dart
- RabbitMQ基礎知識MQ
- webpack基礎知識Web
- javascript基礎知識JavaScript
- ThinkPHP基礎知識PHP
- Laravel基礎知識Laravel
- Redis基礎知識Redis
- Docker基礎知識Docker
- 程式基礎知識
- Envoy基礎知識
- DockerFile基礎知識Docker
- Nginx基礎知識Nginx
- CSS基礎知識CSS
- Java基礎知識Java
- PRML 基礎知識
- BGP基礎知識
- PHP基礎知識PHP