JMS詳解

什麼是JMS
 

它是Java 消息服務

    Java 消息服務是 J2EE (Java 2 Enterprise Edition) 套件的一部分,它提供了標準 API,Java 開發人員可以使用這些 API 來訪問企業消息系統的共同特性。JMS 支持發佈/訂閱和點對點模型,並允許創建由任意 Java 對象組成的消息類型。

體系架構  

JMS有以下元素組成。

  JMS提供者

  連接面向消息中間件的,JMS接口的一個實現。提供者可以是Java平臺的JMS實現,也可以是非Java平臺的面向消息中間件的適配器。

  JMS客戶

  生產或消費消息的基於Java的應用程序或對象。

  JMS生產者

  創建併發送消息的JMS客戶。

  JMS消費者

  接收消息的JMS客戶。

  JMS消息

  包括可以在JMS客戶之間傳遞的數據的對象

  JMS隊列

  一個容納那些被髮送的等待閱讀的消息的區域。隊列暗示,這些消息將按照順序發送。一旦一個消息被閱讀,該消息將被從隊列中移走。

  JMS主題

  一種支持發送消息給多個訂閱者的機制。

JMS模型  

Java消息服務應用程序結構支持兩種模型:

  點對點或隊列模型

  發佈者/訂閱者模型

  在點對點或隊列模型下,一個生產者向一個特定的隊列發佈消息,一個消費者從該隊列中讀取消息。這裏,生產者知道消費者的隊列,並直接將消息發送到消費者的隊列。這種模式被概括爲:

  只有一個消費者將獲得消息

  生產者不需要在接收者消費該消息期間處於運行狀態,接收者也同樣不需要在消息發送時處於運行狀態。

  每一個成功處理的消息都由接收者簽收

  發佈者/訂閱者模型支持向一個特定的消息主題發佈消息。0或多個訂閱者可能對接收來自特定消息主題的消息感興趣。在這種模型下,發佈者和訂閱者彼此不知道對方。這種模式好比是匿名公告板。這種模式被概括爲:

  多個消費者可以獲得消息

  在發佈者和訂閱者之間存在時間依賴性。發佈者需要建立一個訂閱(subscription),以便客戶能夠購訂閱。訂閱者必須保持持續的活動狀態以接收消息,除非訂閱者建立了持久的訂閱。在那種情況下,在訂閱者未連接時發佈的消息將在訂閱者重新連接時重新發布。

  使用Java語言,JMS提供了將應用與提供數據的傳輸層相分離的方式。同一組Java類可以通過JNDI中關於提供者的信息,連接不同的JMS提供者。這一組類首先使用一個連接工廠以連接到隊列或主題,然後發送或發佈消息。在接收端,客戶接收或訂閱這些消息

傳遞消息方式  

JMS現在有兩種傳遞消息的方式。標記爲NON_PERSISTENT的消息最多投遞一次,而標記爲PERSISTENT的消息將使用暫存後再轉送的機理投遞。如果一個JMS服務離線,那麼持久性消息不會丟失但是得等到這個服務恢復聯機時纔會被傳遞。所以默認的消息傳遞方式是非持久性的。即使使用非持久性消息可能降低內務和需要的存儲器,並且這種傳遞方式只有當你不需要接收所有的消息時才使用。

  雖然JMS規範並不需要JMS供應商實現消息的優先級路線,但是它需要遞送加快的消息優先於普通級別的消息。JMS定義了從0到9的優先級路線級別,0是最低的優先級而9則是最高的。更特殊的是0到4是正常優先級的變化幅度,而5到9是加快的優先級的變化幅度。舉例來說: topicPublisher.publish (message, DeliveryMode.PERSISTENT, 8, 10000); //Pub-Sub 或 queueSender.send(message,DeliveryMode.PERSISTENT, 8, 10000);//P2P 這個代碼片斷,有兩種消息模型,映射遞送方式是持久的,優先級爲加快型,生存週期是10000 (以毫秒度量 )。如果生存週期設置爲零,這則消息將永遠不會過期。當消息需要時間限制否則將使其無效時,設置生存週期是有用的。

  JMS定義了五種不同的消息正文格式,以及調用的消息類型,允許你發送並接收以一些不同形式的數據,提供現有消息格式的一些級別的兼容性。

  · StreamMessage -- Java原始值的數據流

  · MapMessage--一套名稱-值對

  · TextMessage--一個字符串對象

  · ObjectMessage--一個序列化的 Java對象

  · BytesMessage--一個未解釋字節的數據流

 

JMS應用程序接口

ConnectionFactory 接口(連接工廠)

  用戶用來創建到JMS提供者的連接的被管對象。JMS客戶通過可移植的接口訪問連接,這樣當下層的實現改變時,代碼不需要進行修改。 管理員在JNDI名字空間中配置連接工廠,這樣,JMS客戶才能夠查找到它們。根據消息類型的不同,用戶將使用隊列連接工廠,或者主題連接工廠。

Connection 接口(連接)

  連接代表了應用程序和消息服務器之間的通信鏈路。在獲得了連接工廠後,就可以創建一個與JMS提供者的連接。根據不同的連接類型,連接允許用戶創建會話,以發送和接收隊列和主題到目標。

Destination 接口(目標)

  目標是一個包裝了消息目標標識符的被管對象,消息目標是指消息發佈和接收的地點,或者是隊列,或者是主題。JMS管理員創建這些對象,然後用戶通過JNDI發現它們。和連接工廠一樣,管理員可以創建兩種類型的目標,點對點模型的隊列,以及發佈者/訂閱者模型的主題。

MessageConsumer 接口(消息消費者)

  由會話創建的對象,用於接收發送到目標的消息。消費者可以同步地(阻塞模式),或異步(非阻塞)接收隊列和主題類型的消息。

MessageProducer 接口(消息生產者)

  由會話創建的對象,用於發送消息到目標。用戶可以創建某個目標的發送者,也可以創建一個通用的發送者,在發送消息時指定目標。

Message 接口(消息)

  是在消費者和生產者之間傳送的對象,也就是說從一個應用程序創送到另一個應用程序。一個消息有三個主要部分:

  消息頭(必須):包含用於識別和爲消息尋找路由的操作設置。

  一組消息屬性(可選):包含額外的屬性,支持其他提供者和用戶的兼容。可以創建定製的字段和過濾器(消息選擇器)。

  一個消息體(可選):允許用戶創建五種類型的消息(文本消息,映射消息,字節消息,流消息和對象消息)。

  消息接口非常靈活,並提供了許多方式來定製消息的內容。

Session 接口(會話)

  表示一個單線程的上下文,用於發送和接收消息。由於會話是單線程的,所以消息是連續的,就是說消息是按照發送的順序一個一個接收的。會話的好處是它支持事務。如果用戶選擇了事務支持,會話上下文將保存一組消息,直到事務被提交才發送這些消息。在提交事務之前,用戶可以使用回滾操作取消這些消息。一個會話允許用戶創建消息生產者來發送消息,創建消息消費者來接收消息。

 

設計目標

     JMS 的基本設計目標是爲了提供一組一致的接口,消息傳遞系統客戶端可以獨立地使用這些接口,而不必關心基礎消息系統的提供商。這樣,客戶端應用程序不僅可以跨計算機體系結構和操作系統進行移植,而且也可以跨消息傳遞產品進行移植。寫到 JMS 的客戶端應用程序將正常工作,而不用在所有符合 JMS 的消息傳遞系統上做修改(這可以與組件所運行的基礎中間件上的 Enterprise Java Beans 組件的獨立性進行比較)。

JMS 也設計成:

     最小化消息傳遞系統提供商爲其產品實現 JMS API 所需的工作量。

     提供了普通消息傳遞系統的大多數功能。

許多消息系統提供商已經爲它們的產品實現了 JMS,允許 Java 訪問它們系統的功能。

JMS 客戶端可以使用 Java 設施

     由於 JMS 客戶端是基於 Java 的,因此它們可以利用現有的 Java API,比如:用於數據庫訪問

的JDBC、JavaBeans 組件模型、用於命名服務的 JNDI、用於客戶端事務控制的 JTA 或用於企業應用程序

服務的任何 J2SE 和 J2EE API。

JMS 細節

什麼是消息?

    在消息傳遞系統中,應用程序之間的通信點是消息本身,因此使用 JMS 的開發人員必須理解消息。

儘管消息傳遞系統之間消息定義區別甚大,但 JMS 提供了統一的方式用於描述和訪問消息。JMS 消息由三部分組成:

消息標題 :用於消息標識。例如,標題用於確定指定的消息是否適合於“訂閱者”。

屬性 :用於特定於應用程序、特定於提供商及可選的標題字段。

消息體 :保存消息的內容。支持幾種格式,其中包括:TextMessages——用於包裝簡單的 String; 和 ObjectMessages——用於包裝任意的 Java 對象(它們必須是可序列化的)。也支持其他的格式。

TextMessages

    TextMessage 用於包裝簡單的 String 對象。在只傳遞字符串的情形下,這是有用的。期望許多消息傳遞系統將以 XML 爲基礎,TextMessages 是它們的自然容器。

    創建 TextMessage 對象是簡單的,如下面兩行代碼所指出的那樣:

TextMessage message =

session.createMessage();

message.setText("hello world");

以這種方式創建的 TextMessage 準備發佈到消息傳遞系統中。

ObjectMessages

    顧名思義,ObjectMessage 是包裝了 Java 對象的消息。任何可序列化的 Java 對象均可用作 ObjectMessage。如果多個對象必須在單個消息中傳輸,那麼可以使用包含幾個可序列化對象的 Collection 對象(比如 List 或 Set)。

   下面展示瞭如何創建 Object 消息:

ObjectMessage message = session.createObjectMessage();

message.setObject(myObject);

構建 JMS 客戶端

   可以遵循下面的基本步驟來構建典型的 JMS 客戶端:

創建到消息傳遞系統提供商的連接。

創建會話用於發送和接收消息。

創建 MessageProducers 和 MessageConsumers 來創建或接收消息。

    一旦這些步驟執行完畢,消息生產的客戶端將創建消息,並把它們發佈到主題,而消息消費的客戶端將偵聽與主題有關的消息,並在它們到達時消費它們。

   爲了詳細展示它是如何工作的,我們研究了典型的消息生產者,它用於在 pub/sub 消息傳遞系統中把消息發佈到特定的主題。注意,爲簡潔起見,省略了所有異常處理代碼。

創建連接

   連接爲客戶端提供了對基礎消息傳遞系統的訪問,並執行資源分配和管理。連接是使用 ConnectionFactory 創建的,而 ConnectionFactory 通常是使用 JNDI 查找的。

   下面這些代碼展示了創建連接過程中涉及的一些步驟:

Context messaging = new InitialContext();

// get JNDI context

TopicConnectionFactory topicConnectionFactory =

(TopicConnectionFactory)

messaging.lookup("TopicConnectionFactory");

TopicConnection topicConnection =

topicConnectionFactory.createTopicConnection();

 

創建會話

    會話是輕量級 JMS 對象,它提供了用於生產和消費消息的上下文。會話用於生成消息生產者和消息消費者,以及用於生成消息本身。

TopicSession session =

topicConnection.createTopicSession(false,

Session.CLIENT_ACKNOWLEDGE);

createTopicSession() 的兩個參數控制事務和消息的確認。

查找主題

    主題(也稱標題、組或頻道)是通過 JNDI 來查找的。主題標識了發送中或接收中的消息。在發佈/閱系統中,訂閱者訂閱了指定的主題,而發佈者把主題與它們發佈的消息關聯。

這裏我們創建了一個稱爲“WeatherData”的主題。

Topic weatherTopic = messaging.lookup("WeatherData");

啓動連接

    在上面的初始化過程中,爲了防止初始化期間出現不可預知的行爲,消息流是被禁止的。一旦初始化完成,必須告訴連接開始消息流。

topicConnection.start();

創建消息生產者

    在發佈/訂閱領域中,生產者把消息發佈到指定主題。下面代碼展示了發佈者的創建及後續的簡單文本消息的生成和發佈。

TopicPublisher publisher =

session.createPublisher(weatherData);

TextMessage message = session.createMessage();

message.setText("temperature: 35 degrees");

publisher.publish(message);

 

創建訂閱者及點對點系統的 JMS 客戶端遵循相似的過程。可以在 [1] 中找到這一過程的完整細節。

結束語

我們已經看到在使用 JMS 來構建基於消息傳遞的應用程序的過程中涉及的基本概念。在編寫 JMS 代碼之前,你將需要訪問符合 JMS 的消息傳遞系統。

-----------------------------------------------------------------------

MessageDrivenBean 在 EJB 2.0 中,對規範的一個基礎性更改是添加了一種全新的企業級 bean 類型,即 MessageDrivenBean。MessageDrivenBean 專門設計來處理入網的 JMS 消息。對於許多開發人員來說,JMS 是一種新的範例,所以本文將花一些時間逐步說明對 JMS 的理解,以及它們在 EJB 2.0 中的用法。 

JMS 是一種與廠商無關的 API,用來訪問消息收發系統。它類似於 JDBC (Java Database Connectivity):這裏,JDBC 是可以用來訪問許多不同關係數據庫的 API,而 JMS 則提供同樣與廠商無關的訪問方法,以訪問消息收發服務。許多廠商目前都支持 JMS,包括 IBM 的 MQSeries、BEA 的 Weblogic JMS service 和 Progress 的 SonicMQ,這只是幾個例子。

JMS 使您能夠通過消息收發服務(有時稱爲消息中介程序或路由器)從一個 JMS 客戶機向另一個 JML 客戶機發送消息。消息是 JMS 中的一種類型對象,由兩部分組成:報頭和消息主體。報頭由路由信息以及有關該消息的元數據組成。消息主體則攜帶着應用程序的數據或有效負載。根據有效負載的類型來劃分,可以將消息分爲幾種類型,它們分別攜帶:簡單文本 (TextMessage)、可序列化的對象 (ObjectMessage)、屬性集合 (MapMessage)、字節流 (BytesMessage)、原始值流 (StreamMessage),還有無有效負載的消息 (Message)。

消息收發系統是異步的,也就是說,JMS 客戶機可以發送消息而不必等待迴應。比較可知,這完全不同於基於 RPC 的(基於遠程過程的)系統,如 EJB 1.1、CORBA 和 Java RMI 的引用實現。在 RPC 中,客戶機調用服務器上某個分佈式對象的一個方法。在方法調用返回之前,該客戶機被阻塞;該客戶機在可以執行下一條指令之前,必須等待方法調用結束。在 JMS 中,客戶機將消息發送給一個虛擬通道(主題或隊列),而其它 JMS 客戶機則預訂或監聽這個虛擬通道。當 JMS 客戶機發送消息時,它並不等待迴應。它執行發送操作,然後繼續執行下一條指令。消息可能最終轉發到一個或許多個客戶機,這些客戶機都不需要作出迴應。

EJB 2.0 中的 JMS EJB 2.0 以兩種方式支持 JMS 的集成:作爲一種 bean 可用的資源,和作爲一個 MessageDrivenBean。當將 JMS 用作一種資源時,使用 JMS API 的 bean 就是消息的產生者或發送者。在這種情況下,bean 將消息發送給稱爲主題或隊列的虛擬通道。另一方面,MessageDrivenBean 則是消息的使用者或接收者。它監聽特定的虛擬通道(主題或隊列),並處理髮送給該通道的消息。爲了更好地理解消息產生者和消息使用者的作用,用 SessionBean bean 來發送一條使用 JMS 的消息,然後使用一個新的 MessageDrivenBean 來使用該同一條消息。

作爲 EJB 2.0 資源的 JMS 會話 bean 和實體 bean 都是基於 RPC 的組件,爲了將各種事務性的組件裝配到一起,這是一種卓越的體系結構。但是,在某些情況下,RPC 的同步性質會成爲一種障礙,這正是 EJB 1.1 中將對 JMS API 的訪問作爲一種資源包括在內的原因。利用 JNDI 環境命名的上下文,bean 可以獲得一個 JMS 工廠,並將一條異步消息發送給主題或隊列(也從 JNDI 獲得),而不必等待迴應。下面是 ShoppingCart bean 的一個例子,它使用 JMS 將 Order 的詳細信息發送給消息收發主題

消息中間件

消息中間件提供企業數據的異步傳輸,通過消息中間件,一些原本互相孤立的業務組件可以組合成一個可靠的、靈活的系統。

消息中間件大致分爲兩類

Point-to-Point(PTP)

Publish-Subscribe(Pub/Sub)

PTP是點對點傳輸消息,建立在消息隊列的基礎上,每個客戶端對應一個消息隊列,客戶端發送消息到對方的消息隊列中,從自己的消息隊列讀取消息。 Pub/Sub是將消息定位到某個層次結構欄目的節點上,Pub/Sub通常是匿名的並能夠動態發佈消息,Pub/Sub必須保證某個節點的所有發佈者(Publisher)發佈的信息準區無誤地發送到這個節點的所有消息訂閱者(Subscriber)。 


JMS定義了Java中訪問消息中間件的接口。

JMS只是接口,並沒有給予實現,實現JMS接口的消息中間件叫JMS Provider,這樣的消息中間件可以從Java裏通過JMS接口進行調用。

JMS和其他企業級Java API的關係

JDBC JMS客戶端可以使用JDBC接口,可以將JDBC和JMS包含在一個事務裏。這種包含可以在EJB裏,也可以直接調用JTA(Java Transaction API)接口實現。

JavaBeans JavaBeans可以用JMS Session發送接收消息。

EJB

對於EJB組件來說,JMS和JDBC一樣,是一個很重要的企業級服務資源。目前的EJB規範定義客戶端只能同步調用EJB,未來的規範將會定義通過一個JMS客戶端發消息異步調用EJB組件。

JTA(Java Transaction API) JMS客戶端可以用JTA啓動事務。JMS Provider可以選擇是否支持分佈式事務。

JTS(Java Transaction Service) JMS可以和JTS一起組成一個分佈式事務,如將發送接收消息和更新數據庫包含在一個事務裏。

JNDI JMS 客戶端通過JNDI調用JMS中的對象。

JMS 消息模型

JMS消息由兩部分構成:header和body。header包含消息的識別信息和路由信息,body包含消息的實際數據。

根據數據格式,JMS消息可分爲以下五種

BytesMessage 消息是字節流。

MapMessage 消息是一系列的命名和值的對應組合。

ObjectMessage 消息是一個流化的Java對象。

StreamMessage 消息是Java中的輸入輸出流。

TextMessage 消息是一個字符串,這種類型將會廣泛用於XML格式的數據。

JMS 消息優先級

郵局發信分爲平信和特快專遞兩種,同樣JMS也根據消息的輕重緩急將消息分爲0-9十個級別。0-4是普通消息,5-9是加急消息。JMS不要求消息中間件嚴格按照這十個優先級發送消息,但必須保證加急消息要先於普通消息到達。

Apusic對JMS的支持

Apusic Application Server包含一個完全遵循JMS接口規範開發的消息中間件,Apusic消息中間件支持通常的兩種消息中間件:PTP和Pub/Sub。

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