|
一、概述
Message,即消息。人與人之間通過消息傳遞信息。言語、眼神、肢體動作都可被視為消息體。當然還有我們經(jīng)常用到的郵件、短信。計算機系統(tǒng)也由消息來主導(dǎo)運行。每一條指令的執(zhí)行,每一個數(shù)據(jù)包的傳遞。軟件系統(tǒng)間的合作也不例外,消息告訴各個系統(tǒng)應(yīng)該怎樣協(xié)作。事件處理機制,也是消息傳送的過程。消息無處不在。 消息分為同步消息和異步消息。同步消息在接收到對方的返回前,需要掛起,直到返回或超時。異步消息只需要發(fā)送消息,不需要對方系統(tǒng)的立即反饋。 同步消息如java RPC調(diào)用,同步調(diào)用依賴于被調(diào)用方,如果被調(diào)用方失敗或網(wǎng)絡(luò)錯誤,那么程序就沒辦法繼續(xù)執(zhí)行下去,造成一個系統(tǒng)最薄弱的環(huán)節(jié)依賴于對方系統(tǒng)。而多個系統(tǒng)通過同步調(diào)用方式耦合在一起的時候,那么可靠性取決于最薄弱的一方系統(tǒng)。而異步調(diào)用能增強一個系統(tǒng)的健壯性。當然,不是任何情況都適合異步調(diào)用,還是那句話,能異步的地方,盡量異步。 異步消息,如同一個郵箱系統(tǒng),我們把信件丟入郵桶,郵遞員會更具上面的地址,送達到這封信要去的地方。郵箱和信件格式由郵局提供定義,比如郵箱需要有一個口子投遞郵件,郵件需要有地址,郵政編碼等等。而這些郵箱具體的加工和制作均交由各自的廠商來完成。 在java消息領(lǐng)域,我們也有一個稱為消息中間件的東西,來提供這樣一個服務(wù)。消息的發(fā)送、消費接口、消息體的格式等都由JMS來定義,而具體的實現(xiàn)由各個消息中間件廠商來實現(xiàn)。JMS是sun公司對于消息中間件的一個規(guī)范。對java領(lǐng)域里的消息起到舉足輕重的作用。以前的消息交互,均各自實現(xiàn)一套格式,如同一個國家的人都用不同的方言跟另外來自不同省份的人交流一樣。自從規(guī)范了普通話,我們的交流成本降低了。這也正如JMS規(guī)范在整個java消息領(lǐng)域的作用。 二、JMS簡介 JMS1.1規(guī)范定義了一些概念和一組API,可以使得在我們利用消息系統(tǒng)的過程中,不依賴于各個廠商的具體實現(xiàn),便能寫出消息代碼。由于不依賴具體廠商實現(xiàn),這樣的代碼有很好的移植性。 JMS1.1定義了的部分概念: 1、JMS客戶端:接收或發(fā)送消息的java系統(tǒng) 2、JMS消息體:系統(tǒng)間發(fā)送的消息體 3、JMS提供商:JMS規(guī)范實現(xiàn)廠商 4、JMS管理對象:預(yù)先配置好的用于JMS客戶端的JMS對象。如ConnectionFactory跟JMS服務(wù)端的連接工廠,Destination 接收和發(fā)送消息的目標地址等 5、JMS Domain:JMS定義了兩種域模型,一種是PTP(point-to-point)即點對點消息傳輸模型,一種是pub/sub(publish-subscribe)即發(fā)布訂閱模型。 PTP通過一個先進先出的queue實現(xiàn)。很多人在這個PTP概念上有所誤解,所謂點對點不是指生產(chǎn)者和消費者只有一個。PTP如下圖所示: 我們可以看到,一個或多個生產(chǎn)者發(fā)送消息,消息m2先抵達了queue,然后m1也發(fā)出了,并一同存在于一個先進先出的queue里面。消費者也存在一個或多個,對queue里的消息進行消費。但消息被隨機的一個消費者消費且僅消費一次。 在pub/sub消息模型中,消息被廣播給所有訂閱者。如下圖: JMS1.1定義了如下接口:
接口關(guān)系如下: 可以看到一個JMS應(yīng)用的發(fā)送端的標準流程是:創(chuàng)建連接工廠>創(chuàng)建連接>創(chuàng)建session>創(chuàng)建發(fā)送者>創(chuàng)建消息體>發(fā)送消息到Destination(queue或topic)。 接收端則為:創(chuàng)建連接工廠>創(chuàng)建連接>創(chuàng)建session>創(chuàng)建接收者>創(chuàng)建消息監(jiān)聽器監(jiān)聽某Destination的消息>獲取消息并執(zhí)行業(yè)務(wù)邏輯 下面展示了JMS的編碼模板: 發(fā)送端:
接收端:
消息偵聽者:
我們安裝了ApacheMQ之后,啟動本地MQ服務(wù),便能測試這幾個類的執(zhí)行方式,觀察執(zhí)行過程。我們可以發(fā)現(xiàn)消息僅被消費了一次,JMS提供商必須保證一條消息不會重復(fù)被消費,當然更不能丟失。 在PTP下,我們建立一個queue以后,如果沒有消費者連入該queue,那么消息生產(chǎn)者發(fā)送的消息將堵塞在queue里面,直到有消費者來消費。如果消費者出現(xiàn)故障,不再連入queue,消息還會保存在queue里面,等待下次消費者的連入,再進行消費。在pub/sub模型下,如果消費者出現(xiàn)故障,那么所有的消息,將不在為之保留,下次連接之時,只能消費此時生產(chǎn)者發(fā)送的消息。JMS于是定義了另一種訂閱者,叫Durable Subscription(持久訂閱者),該訂閱者在第一次連上topic后,就注冊了該topic的消息,消息會在消費者不可用的情況下為之保留消息,并在其再次連上topic后,重推消息給消費者。 理解了JMS中的兩種消息模型以后,我們來說說JMS中的消息體格式。JMS對消息體定為三個部分 1)head 消息頭信息 2)properties 消息屬性值 3)body 消息內(nèi)容。如下圖所示: 其含義大致解釋如下:
再談消息可靠性 在上面,談及消息體格式定義中,有個字段 JMSDeliveryMode用來表示該消息發(fā)送后,JMS提供商應(yīng)該怎么處理消息。PERSISTENT(持久化)的消息在JMS服務(wù)器中持久化。接收端如果采用點對點的queue方式或者Durable Subscription(持久訂閱者)方式,那么消息可保證只且只有一次被成功接收。NON_PERSISTENT(非持久化)的消息在JMS服務(wù)器關(guān)閉或宕機時,消息丟失。根據(jù)發(fā)送端和接收端采用的方式,列出如下可靠性表格,以作參考。 引用 注意:以下的可靠性不包括JMS服務(wù)器由于資源關(guān)系,造成的消息不能持久化等因素引起的不可靠(該類不可靠應(yīng)該是JMS提供商或硬件引起的的資源和處理能力的極限問題,應(yīng)該由管理人員解決)。也不包括消息由于超時時間造成的銷毀丟失。
消息的通知確認 在客戶端接收了消息之后,JMS服務(wù)怎樣有效確認消息是否已經(jīng)被客戶端接收呢?Session session=connection.createSession(false,Session.AUTO_ACKNOWLEDGE);這段代碼創(chuàng)建一個非事務(wù)性的session,并采用auto_acknowledge方式通知JMS服務(wù)器。如果采用事務(wù)性session時,通知會伴隨session的commit/rollback同時發(fā)送通知。在我們采用非事務(wù)session時,有三種通知方式。
JMS就先簡要的介紹到這里,詳細資料請參看JMS1.1規(guī)范。關(guān)于ActiveMQ的文章文章請繼續(xù)關(guān)注 ActiveMQ分享(二) |
|
|