JMS基礎概念

Java 消息服務 (JMS) 基礎

Message Queue 是一種實現了 Java 消息服務 (JMS) 開放標準的企業消息傳送系統:它是 JMS 提供者。因此,JMS 概念是理解 Message Queue 服務工作方式的基礎。

JMS 規範規定了一套管理可靠異步消息傳送的規則和語義。該規範定義了消息結構、編程模型和 API。

本節說明了理解本書其餘各章所需的 JMS 概念和術語。涵蓋下列主題:

JMS 消息結構

在 Message Queue 中,數據是使用 JMS 消息進行交換的。根據 JMS 規範,生產者客戶機創建的消息包括三部分:標題、屬性和主體。

標題

每條 JMS 消息都必須具有標題。標題字段包含用於路由和識別消息的值。

可以通過多種方式來設置標題的值:

  • 由 JMS 提供者在生成或傳送消息的過程中自動設置
  • 由生產者客戶機通過在創建消息生產者時指定的設置進行設置
  • 由生產者客戶機逐一對各條消息進行設置

有關 JMS 定義的標題字段的信息,請參見 Message Queue Developer's Guide for Java Clients 或 Message Queue Developer's Guide for C Clients。可以通過這些標題字段定義消息的目標、到期時間及其優先級等。

屬性

消息可以包含稱作屬性的可選標題字段。它們是以屬性名和屬性值對的形式指定的。可以將屬性視爲消息標題的擴展,其中可以包括以下信息:創建數據的進程、數據的創建時間以及每條數據的結構。JMS 提供者也可以添加影響消息處理的屬性,如是否應壓縮消息或如何在消息生命週期結束時廢棄消息。

JMS 提供者可以將消息屬性用作選擇器,以對消息進行排序和路由。生產者客戶機可以在消息中放置特定於應用程序的屬性;而消費者客戶機可以選擇只接收具有特定屬性值的消息。例如,消費者客戶機可能只請求獲得有關新澤西州兼職僱員工資單的消息。不符合指定的選擇標準的消息將不會傳送給該客戶機。

選擇器簡化了消費者客戶機的工作,並消除了向不需要這些消息的客戶機傳送消息的開銷。不過,由於要處理選擇標準,它們也會增加消息服務的一些開銷。在 JMS 規範中對消息選擇器語法和語義進行了簡要說明。

消息主體類型

JMS 消息的類型決定其主體的內容,如表 1-1 中所示。

表 1-1 消息主體類型 

類型

說明

StreamMessage

一種主體中包含 Java 基元值流的消息。其填充和讀取均按順序進行。

MapMessage

一種主體中包含一組名-值對的消息。沒有定義條目順序。

TextMessage

一種主體中包含 Java 字符串的消息(例如,XML 消息)。

ObjectMessage

一種主體中包含序列化 Java 對象的消息。

BytesMessage

一種主體中包含連續字節流的消息。

JMS 編程模型

JMS 編程模型支持異步消息傳送服務體系結構:JMS 客戶機通過 JMS 消息服務交換消息。JMS 提供者提供執行 JMS 消息傳送所需的對象;這些對象用於實現 JMS 應用程序編程接口 (API)。

本節說明 JMS 消息傳送所需的編程對象,並介紹用於發送和接收消息的傳送模型(點對點及發佈/訂閱)。

編程對象

圖 1-3 中顯示了用於設置 JMS 客戶機以進行消息傳送的對象。

圖 1-3 JMS 編程對象

[D]

在 JMS 編程模型中,JMS 客戶機使用連接工廠對象 (ConnectionFactory) 創建一個連接,向 JMS 消息服務器發送消息以及從 JMS 消息服務器接收消息均通過此連接來進行。連接對象 (Connection) 表示客戶機與消息服務器之間的活動連接。

創建連接時,將分配通信資源以及驗證客戶機。這是一個相當重要的對象,大多數客戶機均使用一個連接來進行所有的消息傳送。

該連接用於創建會話對象 (Session)。會話是一個用於生成和使用消息的單線程上下文。它用於創建消息以及發送和接收消息的生產者和消費者,併爲所傳送的消息定義發送順序。會話通過大量確認選項或通過事務來支持可靠傳送。

客戶機使用消息生產者對象 (MessageProducer) 向指定的物理目標(在 API 中由目標對象表示)發送消息。消息生產者可指定一個默認的消息標題值,例如,傳送模式(持久性與非持久性)、優先級和有效期,以控制生產者向物理目標發送的所有消息。

同樣,客戶機使用消息消費者對象 (MessageConsumer) 從指定的物理目標(在 API 中表示爲目標對象)接收消息。共有兩種類型的目標,分別是隊列主題,具體類型取決於消息傳送模型。

消息消費者可以利用消息選擇器,使消息服務只傳送那些屬性匹配特定選擇標準的消息。

消息消費者可以支持同步或異步消息使用。

  • 同步使用是指,消費者明確請求傳送消息並隨後使用該消息。
  • 異步使用是指,自動將消息傳送給爲消費者註冊的消息偵聽器對象 (MessageListener)。當會話線程調用消息偵聽器對象的 onMessage() 方法時,客戶機將使用該消息。

編程域:消息傳送模型

JMS 支持兩種截然不同的消息傳送模型:點對點模型和發佈/訂閱模型。

點對點(隊列目標)     消息從一個生產者傳送至單個消費者。在此傳送模型中,目標類型是隊列。消息首先被傳 送至隊列目標,然後從該隊列將消息傳送至對此隊列進行註冊的某個消費者,一次只傳送一條消息。可以向隊列目標發送消息的生產者的數量沒有限制,但每條消息 只能發送至、並由一個消費者成功使用。如果沒有已經向隊列目標註冊的消費者,隊列將保留它收到的消息,並在某個消費者對該隊列進行註冊時將消息傳送給該消 費者。

發佈/訂閱(主題目標)     消息從一個生產者傳送至任意數量的消費者。在此傳送模型中,目標類型是主題。消息首先被傳送至主題目標,然後傳送至所有訂閱此主題的活動消費者。可以向主題目標發送消息的生產者的數量沒有限制,並且每個消息可以發送至任意數量的訂閱消費者。

主題目標也支持長期訂閱。長期訂閱表示消費者已註冊了主題目標,但在消息到達目標時該消費者可以處於非活動狀態。當消費者再次處於活動狀態時,將會接收該消息。如果消費者均沒有註冊某個主題目標,該主題只保留註冊了長期訂閱的非活動消費者的消息。

這兩種消息傳送模型使用三組表示不同編程的 API 對象(其語義略有不同)進行處理,如表 1-2 所示。

表 1-2 JMS 編程域和對象 

基本類型(統一域)

點對點域

發佈/訂閱域

Destination(Queue 或 Topic)1

Queue

Topic

ConnectionFactory

QueueConnectionFactory

TopicConnectionFactory

Connection

QueueConnection

TopicConnection

Session

QueueSession

TopicSession

MessageProducer

QueueSender

TopicPublisher

MessageConsumer

QueueReceiver

TopicSubscriber

 

1取決於編程方法,您必須指定特定的目標類型。

JMS 版本 1.1 中引入了統一域。如果需要遵循早期的 1.02b 規範,可以使用特定於域的 API。使用特定於域的 API 還具有編程接口爲全新接口的優點,可以防止出現某些類型的編程錯誤:例如,爲隊列目標創建長期訂戶。不過,特定於域的 API 也有缺點,即無法合併同一事務或會話中的點對點操作及發佈/訂閱操作。如果需要執行該操作,則應選擇統一的域 API。

Message Queue 產品包含的示例應用程序以及 Message Queue 文檔中提供的很多代碼示例均使用單獨的編程域。

可靠消息傳送

可以將消息的傳送模式設置爲持久性或非持久性;此模式控制消息傳送的可靠性。

  • 保證只將持久性消息傳送併成功使用一次。在消息服務發生故障時,持久性消息不會丟失。對於這些消息,可靠性是優先考慮的因素。
  • 保證最多將非持久性消息傳送一次。在消息服務發生故障時,非持久性消息將會丟失。對於這些消息,可靠性並非主要的考慮因素。

對於持久性消息,確保可靠性有兩個方面。一方面,通過使用確認和事務來確保成功生成和使用消息。另一方面,通過將消息放在持久性存儲庫中,確保在將持久性消息傳送至消費者之前消息服務不會丟失持久性消息。

以下各節介紹這兩個方面的可靠性保證措施。

確認/事務

可靠的消息傳送取決於保證成功地將持久性消息從消息生產者傳送到消息服務器上的物理目標,然後再成功地從該物理目標傳送到消息消費者。這種可靠性可以通過 JMS 會話支持的兩個通用機制實現:確認事務。事務可以是本地事務或分佈式事務(由分佈式事務管理器控制)。

確認

確認是在客戶機與消息服務間發送的消息,用於確保可靠地進行傳送。

生成消息時,消息服務確認它已收到傳送的消息,將該消息置於其目標中並進行持久性存儲。生產者的 send() 方法會阻塞,直至確認返回爲止。

使用消息時,客戶機確認已收到從某個目標傳送來的消息並已使用,然後消息服務從該目標中刪除消息。JMS 規定了不同的確認模式,它們分別代表不同的可靠性級別。在其中的某些模式下,客戶機會阻塞,等待消息服務器確認已刪除某個消息,並因此無法重新傳送該消息。

本地事務

可以將會話配置爲已處理,這樣,可以將一個或多個消息的生成和/或使用組成原子單元,也就是事務。JMS API 提供了啓動、提交或回滾事務的方法。

在事務中生成或使用消息時,消息服務跟蹤各個發送和接收 過程,並在 JMS 客戶機發出提交事務的調用時完成這些操作。如果事務中特定的發送或接收操作失敗,則出現異常。客戶機代碼通過忽略異常、重試操作或回滾整個事務來處理異 常。在事務提交時,將完成其所有操作。在事務進行回滾時,將取消所有成功的操作。

本地事務的範圍始終爲一個會話。也就是說,可以將單個會話的上下文中執行的一個或多個生產者或消費者操作組成一個本地事務。

由於事務的範圍只能爲單個的會話,因此不存在既包括消息生成又包括消息使用的端對端事務。(換句話說,至目標的消息傳送和隨後進行的至客戶機的消息傳送不能放在同一個事務中。)

分佈式事務

JMS 規範還支持分佈式事務。也就 是說,消息的生成和使用可作爲較大的分佈式事務的一部分,該分佈式事務中包括涉及其他資源管理器(如數據庫系統)的操作。在分佈式事務中,分佈式事務管理 器使用在 Java 事務 API (JTA)、XA 資源 API 規範中定義的兩階段提交協議跟蹤和管理由多個資源管理器(如消息服務和數據庫管理器)執行的操作。在 Java 中,JTA 規範說明了資源管理器和分佈式事務管理器之間的交互。

支持分佈式事務是指消息傳送客戶機可通過 JTA 定義的 XAResource 接口參與分佈式事務。此接口定義了實現兩階段提交的許多方法。當客戶機端進行 API 調用時,JMS 消息服務只與分佈式事務管理器(由 Java 事務服務 (JTS) 提供)協作來跟蹤分佈式事務中的各種發送和接收操作、事務狀態並完成消息傳送操作。

處理本地事務時,客戶機通過忽略異常、重試操作或回滾整個分佈式事務來處理異常。

持久性存儲器

另一方面的可靠性就是確保在將持久性消息傳送至消費者之前,消息服務不會將它們丟失。這意味着,當持久性消息到達其物理目標時,消息服務器必須將其置於持久性數據存儲庫中。如果消息服務器由於某種原因發生故障,它可以恢復此消息並將其傳送至相應的消費者。

消息服務器還必須持久性地存儲長期訂閱。否則,當消息服務器發生故障時,就無法向長期訂戶傳送消息;消息到達主題目標後,長期訂戶會恢復活動狀態。

要保證成功傳送消息,消息傳送應用程序必須將消息指定爲持久性消息,並將它們傳送給具有長期訂閱的主題目標或傳送給隊列目標。

JMS 受管理對象

JMS 編程模型中使用的兩個對象(連接工廠和目標)可能會因提供者的 JMS 規範實現而有所不同。

  • 連接工廠對象用於創建以下連接:其行爲取決於提供者傳送消息時所採用的協議和機制。
  • 目標對象用於指定代理上的物理目標的名稱,它取決於具體的命名約定及消息服務器上的物理目標的功能。

爲使提供者在定義這些對象時具有最大限度的靈活性,同時使客戶機具有移植性,JMS 規範定義了受管理對象(針對連接工廠和目標),其中封裝了特定於提供者的信息。這些對象由管理員創建和配置,並存儲在 JNDI 名稱空間(對象存儲庫)中,由客戶機通過標準 JNDI 查找代碼來訪問。

受管理對象允許 JMS 客戶機使用邏輯名稱查找和引用特定於提供者的對象。這樣,客戶機代碼無需知道提供者使用的特定命名語法、尋址語法或可配置屬性。從而使代碼與提供者無關。

受管理對象一節提供了有關 Message Queue 中使用的受管理對象的其他信息。


 

JMS 規範並不要求您必須使用 JNDI 查找來訪問受管理對象。客戶機代碼可以實例化連接工廠和目標對象,並設置其屬性值。不過,這意味着客戶機代碼無法移植到其他提供者上。


 

 

 

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