從入門到精通的ActiveMQ(一)

這是關於消息中間件ActiveMQ的一個系列專題文章,將涵蓋JMS、ActiveMQ的初步入門及API詳細使用、兩種經典的消息模式(PTP and Pub/Sub)、與Spring整合、ActiveMQ集羣、監控與配置優化等。話不多說,我們來一起瞧一瞧!

JMS
首先來說較早以前,也就是沒有JMS的那個時候,很多應用系統存在一些缺陷:

1.通信的同步性

client端發起調用後,必須等待server處理完成並返回結果後才能繼續執行

2.client 和 server 的生命週期耦合太高

client進程和server服務進程都必須可用,如果server出現問題或者網絡故障,那麼client端會收到異常

3.點對點通信

client端的一次調用只能發送給某一個單獨的服務對象,無法一對多

JMS,即Java Message Service,通過面向消息中間件(MOM:Message Oriented Middleware)的方式很好的解決了上面的問題。大致的過程是這樣的:發送者把消息發送給消息服務器,消息服務器將消息存放在若干隊列/主題中,在合適的時候,消息服務器會將消息轉發給接受者。在這個過程中,發送和接受是異步的,也就是發送無需等待,而且發送者和接受者的生命週期也沒有必然關係;在pub/sub模式下,也可以完成一對多的通信,即讓一個消息有多個接受者。
從入門到精通的ActiveMQ(一)
JMS

需要注意的是,JMS只是定義了Java訪問消息中間件的接口,其實就是在包javax.jms中,你會發現這個包下除了異常定義,其他都是interface。我們可以掃一眼,比如Message:從入門到精通的ActiveMQ(一)
Message接口

我想你應該發現了,JMS只給出接口,然後由具體的中間件去實現,比如ActiveMQ就是實現了JMS的一種Provider,還有阿里巴巴的RocketMQ(後續專題中在爲大家介紹)。這些消息中間件都符合JMS規範。說起規範,自然要定義一些術語:

Provider/MessageProvider:生產者

Consumer/MessageConsumer:消費者

PTP:Point To Point,點對點通信消息模型

Pub/Sub:Publish/Subscribe,發佈訂閱消息模型

Queue:隊列,目標類型之一,和PTP結合

Topic:主題,目標類型之一,和Pub/Sub結合

ConnectionFactory:連接工廠,JMS用它創建連接

Connnection:JMS Client到JMS Provider的連接

Destination:消息目的地,由Session創建

Session:會話,由Connection創建,實質上就是發送、接受消息的一個線程,因此生產者、消費者都是Session創建的

初步來看,Session非常核心,因爲很多東西都是它創建的,在後文中可以通過代碼來進一步認識這些術語。

ActiveMQ QuickStart
ActiveMQ是Apache出品的,非常流行的消息中間件,可以說要掌握消息中間件,需要從ActiveMQ開始,要掌握更加強大的RocketMQ,也需要ActiveMQ的基礎,因此我們來搞定它吧。官網地址:http://activemq.apache.org/,目前最新的版本是5.14.4,我這邊將以最新版來講解。這篇文章主要是ActiveMQ的初步,因此我這邊暫時用windows版本,後期採用Linux。![](https://s4.51cto.com/images/blog/202004/20/09de0cf4fdeefebe4a6f86deab585ba4.jpg?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
ActiveMQ目錄結構

bin下面存放的是ActiveMQ的啓動腳本activemq.bat,注意分32、64位

conf裏面是配置文件,重點關注的是activemq.xml、jetty.xml、jetty-realm.properties。在登錄ActiveMQ Web控制檯需要用戶名、密碼信息;在JMS CLIENT和ActiveMQ進行何種協議的連接、端口是什麼等這些信息都在上面的配置文件中可以體現。

data目錄下是ActiveMQ進行消息持久化存放的地方,默認採用的是kahadb,當然我們可以採用leveldb,或者採用JDBC存儲到MySQL,或者乾脆不使用持久化機制。

webapps,注意ActiveMQ自帶Jetty提供Web管控臺

lib中ActiveMQ爲我們提供了分功能的JAR包,當然也提供了activemq-all-5.14.4.jar

在JDK安裝沒有問題的情況下,直接activemq.bat啓動它,並訪問Web控制檯!從入門到精通的ActiveMQ(一)
ActiveMQ Start

到這裏,ActiveMQ就已經啓動了,So easy~

訪問ActiveMQ web控制檯的用戶名、密碼在哪裏配置的?URL當中的端口是在哪裏配置的?從入門到精通的ActiveMQ(一)
username/pwd 4 access web從入門到精通的ActiveMQ(一)
port 4 web console

Write Code 4 ActiveMQ
來一個HelloWorld級別的例子,來感受下ActiveMQ。具體來說,我這邊會寫一個生產者用於發送消息,一個消費者用於接收消息。實際上,JMS是有“套路”的,下面我將以生產者爲例詳細說明。

第一步:創建ConnectionFactory連接工廠從入門到精通的ActiveMQ(一)
ConnectionFactory

實際上,這裏是存在安全隱患的,也就是任何人一旦知道MQ的地址,就可以連接訪問了,我們可以在activemq.xml中配置指定的用戶、密碼才能訪問ActiveMQ。

關於broker_bind_url,默認就是tcp://localhost:61616,說明是採用TCP協議,61616端口。其實對於ActiveMQ不僅僅支持TCP協議,還有其他協議,開啓了多個端口。從入門到精通的ActiveMQ(一)
第二步:創建Connection從入門到精通的ActiveMQ(一)
Connection

Connection就代表了應用程序和消息服務器之間的通信鏈路。獲得了連接工廠後,就可以創建Connection。

事實上,ConnectionFactory存在重載方法:

Connection createConnection(String username,String password)

也就是說我們也可以在這裏指定用戶名、密碼進行驗證

第三步:創建Session從入門到精通的ActiveMQ(一)
Session

Session,用於發送和接受消息,而且是單線程的,支持事務的。如果Session開啓事務支持,那麼Session將保存一組信息,要麼commit到MQ,要麼回滾這些消息。Session可以創建MessageProducer/MessageConsumer。

第四步:創建Destination從入門到精通的ActiveMQ(一)
Destination

所謂消息目標,就是消息發送和接受的地點,要麼queue,要麼topic。

第五步:創建MessageProducer從入門到精通的ActiveMQ(一)
MessageProducer

第六步:設置持久化方式從入門到精通的ActiveMQ(一)
持久化方式設置

第七步:定義消息對象,併發送從入門到精通的ActiveMQ(一)
Message

生產者和消費者之間傳遞的對象,由3個主要部分構成:

消息頭(路由)+消息屬性(消息選擇器,以後介紹)+消息體(JMS規範的5種類型消息)從入門到精通的ActiveMQ(一)
消息類型

第八步:釋放連接從入門到精通的ActiveMQ(一)
release resource

必須close connection,只有這樣ActiveMQ纔會釋放資源!

消費者的代碼和上面非常類似,只不過就是創建MessageConsumer進行receive而已,注意receive()/receive(long)/receiveNoWait(),這些說明消費者可以採用阻塞模式、非阻塞模式接受消息。

程序運行後,我們來看一下管控臺:從入門到精通的ActiveMQ(一)
ActiveMQ Web Info

Messages Enqueued:表示生產了多少條消息,記做P

Messages Dequeued:表示消費了多少條消息,記做C

Number Of Consumers:表示在該隊列上還有多少消費者在等待接受消息

Number Of Pending Messages:表示還有多少條消息沒有被消費,實際上是表示消息的積壓程度,就是P-C

在說說Session
在通過Connection創建Session的時候,需要設置2個參數,一個是否支持事務,另一個是簽收的模式。我們重點說一下簽收模式:從入門到精通的ActiveMQ(一)
簽收模式

什麼是簽收?通俗點說,就是消費者接受到消息後,需要告訴消息服務器,我收到消息了。當消息服務器收到回執後,本條消息將失效。因此簽收將對PTP模式產生很大影響。如果消費者收到消息後,並不簽收,那麼本條消息繼續有效,很可能會被其他消費者消費掉!

AUTO_ACKNOWLEDGE:表示在消費者receive消息的時候自動的簽收

CLIENT_ACKNOWLEDGE:表示消費者receive消息後必須手動的調用acknowledge()方法進行簽收

DUPS_OK_ACKNOWLEDGE:籤不簽收無所謂了,只要消費者能夠容忍重複的消息接受,當然這樣會降低Session的開銷

在實際中,我們應該採用哪種簽收模式呢?CLIENT_ACKNOWLEDGE,採用手動的方式較自動的方式可能更好些,因爲接收到了消息,並不意味着成功的處理了消息,假設我們採用手動簽收的方式,只有在消息成功處理的前提下才進行簽收,那麼只要消息處理失敗,那麼消息還有效,仍然會繼續消費,直至成功處理!

關於消息的priority/ttl/deliveryMode
消息有優先級及存活時間,在MessageProducer進行send的時候,存在多個重載方法,我們來看一下:從入門到精通的ActiveMQ(一)
send

在上面的code當中,我們創建生產者的時候,指定了Destination,設置了持久化方式,實際上這些都可以不必指定的,而是到send的時候指定。而且在實際業務開發中,往往根據各種判斷,來決定將這條消息發往哪個Queue,因此往往不會在MessageProducer創建的時候指定Destination。

TTL,消息的存活時間,一句話:生產者生產了消息,如果消費者不來消費,那麼這條消息保持多久的有效期

priority,消息優先級,0-9。0-4是普通消息,5-9是加急消息,消息默認級別是4。注意,消息優先級只是一個理論上的概念,並不能絕對保證優先級高的消息一定被消費者優先消費!也就是說ActiveMQ並不能保證消費的順序性!

deliveryMode,如果不指定,默認是持久化的消息。如果可以容忍消息的丟失,那麼採用非持久化的方式,將會改善性能、減少存儲的開銷。

OK,Do you get it?See u next time~

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