ActiveMQ從入門到精通(一)

加瓦一枚發表於2018-12-28

這是關於訊息中介軟體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模式下,也可以完成一對多的通訊,即讓一個訊息有多個接受者。

JMS

需要注意的是,JMS只是定義了Java訪問訊息中介軟體的介面,其實就是在包javax.jms中,你會發現這個包下除了異常定義,其他都是interface。我們可以掃一眼,比如Message:

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。

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 Start

到這裡,ActiveMQ就已經啟動了,So easy~ 

訪問ActiveMQ web控制檯的使用者名稱、密碼在哪裡配置的?URL當中的埠是在哪裡配置的?

username/pwd 4 access web 

port 4 web console

 


Write Code 4 ActiveMQ

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

第一步:建立ConnectionFactory連線工廠

ConnectionFactory

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

關於broker_bind_url,預設就是tcp://localhost:61616,說明是採用TCP協議,61616埠。其實對於ActiveMQ不僅僅支援TCP協議,還有其他協議,開啟了多個埠。

第二步:建立Connection

Connection

Connection就代表了應用程式和訊息伺服器之間的通訊鏈路。獲得了連線工廠後,就可以建立Connection。

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

Connection createConnection(String username,String password) 

也就是說我們也可以在這裡指定使用者名稱、密碼進行驗證

第三步:建立Session

Session

Session,用於傳送和接受訊息,而且是單執行緒的,支援事務的。如果Session開啟事務支援,那麼Session將儲存一組資訊,要麼commit到MQ,要麼回滾這些訊息。Session可以建立MessageProducer/MessageConsumer。

第四步:建立Destination

Destination

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

第五步:建立MessageProducer

MessageProducer

第六步:設定持久化方式

持久化方式設定

第七步:定義訊息物件,併傳送

Message

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

訊息頭(路由)+訊息屬性(訊息選擇器,以後介紹)+訊息體(JMS規範的5種型別訊息)

訊息型別

第八步:釋放連線

release resource

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

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

程式執行後,我們來看一下管控臺:

ActiveMQ Web Info

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

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

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

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

 


在說說Session

在通過Connection建立Session的時候,需要設定2個引數,一個是否支援事務,另一個是簽收的模式。我們重點說一下簽收模式:

簽收模式

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

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

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

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

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

 


關於訊息的priority/ttl/deliveryMode

訊息有優先順序及存活時間,在MessageProducer進行send的時候,存在多個過載方法,我們來看一下:

send

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

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

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

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

 

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



作者:張豐哲
連結:https://www.jianshu.com/p/ecdc6eab554c
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。

相關文章