隨筆 - 1, 文章 - 44, 評(píng)論 - 2, 引用 - 0
          數(shù)據(jù)加載中……

          消息傳遞和 Java 消息服務(wù)(JMS)

          消息傳遞系統(tǒng)用于構(gòu)建高可靠、可伸縮及靈活的分布式應(yīng)用程序。本文從大體上討論了消息傳遞系統(tǒng),簡(jiǎn)要敘述了它們的特性及類型,然后描述開發(fā)人員如何可以使用 Java 消息服務(wù)(Java Message Service ,JMS) 編寫基于消息的應(yīng)用程序。

          正如許多以前在同步、可靠性、可伸縮性和安全性方面的未知問題一樣,分布式應(yīng)用程序潛在的問題也是不斷增長(zhǎng)的。一種解決方案是建立在松散耦合組件基礎(chǔ)上的消息傳遞系統(tǒng),這些組件之間通過消息進(jìn)行通信。

          Java 消息服務(wù)提供了一致的 API 集合,讓開發(fā)人員可以訪問許多消息傳遞系統(tǒng)產(chǎn)品的公共特性。

          什么是消息傳遞系統(tǒng)?
          從它的本質(zhì)上講,消息傳遞系統(tǒng)允許不同的非耦合應(yīng)用程序以異步方式進(jìn)行可靠通信。消息傳遞系統(tǒng)體系結(jié)構(gòu)一般用各個(gè)組件間的點(diǎn)對(duì)點(diǎn)關(guān)系代替客戶端/服務(wù)器模型,其中每個(gè)點(diǎn)可以發(fā)送消息到其他點(diǎn),或從其他點(diǎn)接收消息。

          相對(duì)于更加傳統(tǒng)的分布式計(jì)算模型,消息傳遞系統(tǒng)提供了許多強(qiáng)大的優(yōu)勢(shì)。首先,它們倡議在消息消費(fèi)者和消息生產(chǎn)者之間進(jìn)行“松散耦合”。在生產(chǎn)者和消費(fèi)者之間存在著高級(jí)匿名:對(duì)于消息消費(fèi)者,它不關(guān)心 誰 產(chǎn)生消息,在網(wǎng)絡(luò)上生產(chǎn)者在 哪里,或者消息是 何時(shí) 產(chǎn)生的。

          這使得可以構(gòu)建動(dòng)態(tài)、可靠和靈活的系統(tǒng),由此可以修改子應(yīng)用程序的整體組合,而不會(huì)影響到系統(tǒng)的其余部分。 消息傳遞系統(tǒng)的其他優(yōu)勢(shì)包括高可伸縮性(商業(yè)實(shí)現(xiàn)鼓吹可以支持好幾萬個(gè)客戶端,以及支持每秒進(jìn)行好幾萬個(gè)操作)、容易集成到異構(gòu)網(wǎng)絡(luò)以及由于減少了單點(diǎn)故障而提高了可靠性。

          由于消息傳遞系統(tǒng)固有的可靠性和可伸縮性,所以它們用于解決許多商業(yè)和計(jì)算科學(xué)問題。例如,它們是這樣的一些不同的應(yīng)用程序的基礎(chǔ):工作流、網(wǎng)絡(luò)管理、通信服務(wù)(通過 IP 的語音、有聲郵件、尋呼機(jī)和電子郵件)、客戶服務(wù)、天氣預(yù)報(bào)和供應(yīng)鏈管理等系統(tǒng)。此外,消息傳遞系統(tǒng)是無價(jià)的,因?yàn)樗鳛?#8220;glue”(膠水)把完全不同的系統(tǒng)聯(lián)系在一起,使之能夠合并和獲取消息。

          消息系統(tǒng)類型
          通常使用兩種消息傳遞系統(tǒng)模型。

          發(fā)布/訂閱
          發(fā)布/訂閱 (pub/sub) 消息傳遞系統(tǒng)支持事件驅(qū)動(dòng)模型,在這種模型中,信息消費(fèi)者和生產(chǎn)者參與消息的傳輸。生產(chǎn)者“發(fā)布”事件,而消費(fèi)者“訂閱”感興趣的事件并消費(fèi)事件。生產(chǎn)者把消息把與特定主題關(guān)聯(lián)起來,然后消息傳遞系統(tǒng)根據(jù)消費(fèi)者所注冊(cè)的感興趣主題,把消息路由給消費(fèi)者。

          點(diǎn)對(duì)點(diǎn)
          在點(diǎn)對(duì)點(diǎn)消息傳遞系統(tǒng)中,消息是被路由到各個(gè)消費(fèi)者的,該消費(fèi)者維護(hù)“傳入”消息隊(duì)列。消息傳遞應(yīng)用程序發(fā)送消息到指定隊(duì)列,然后客戶端從隊(duì)列中檢索消息。 供應(yīng)商經(jīng)常會(huì)支持點(diǎn)對(duì)點(diǎn)模型或發(fā)布/訂閱消息傳遞模型,或者同時(shí)支持這兩種模型。

          既然已經(jīng)從大體上認(rèn)識(shí)了消息系統(tǒng),現(xiàn)在讓我們來看一下 Java 開發(fā)人員是如何可以利用它們的能力的。

          Java 消息服務(wù)
          Java 消息服務(wù)是 J2EE (Java 2 Enterprise Edition) 套件的一部分,它提供了標(biāo)準(zhǔn) API,Java 開發(fā)人員可以使用這些 API 來訪問企業(yè)消息系統(tǒng)的共同特性。JMS 支持發(fā)布/訂閱和點(diǎn)對(duì)點(diǎn)模型,并允許創(chuàng)建由任意 Java 對(duì)象組成的消息類型。

          設(shè)計(jì)目標(biāo)
          JMS 的基本設(shè)計(jì)目標(biāo)是為了提供一組一致的接口,消息傳遞系統(tǒng)客戶端可以獨(dú)立地使用這些接口,而不必關(guān)心基礎(chǔ)消息系統(tǒng)的提供商。 這樣,客戶端應(yīng)用程序不僅可以跨計(jì)算機(jī)體系結(jié)構(gòu)和操作系統(tǒng)進(jìn)行移植,而且也可以跨消息傳遞產(chǎn)品進(jìn)行移植。寫到 JMS 的客戶端應(yīng)用程序?qū)⒄9ぷ鳎挥迷谒蟹?JMS 的消息傳遞系統(tǒng)上做修改(這可以與組件所運(yùn)行的基礎(chǔ)中間件上的 Enterprise Java Beans 組件的獨(dú)立性進(jìn)行比較)。

          JMS 也設(shè)計(jì)成:

          最小化消息傳遞系統(tǒng)提供商為其產(chǎn)品實(shí)現(xiàn) JMS API 所需的工作量。
          提供了普通消息傳遞系統(tǒng)的大多數(shù)功能。
          許多消息系統(tǒng)提供商已經(jīng)為它們的產(chǎn)品實(shí)現(xiàn)了 JMS,允許 Java 訪問它們系統(tǒng)的功能。

          JMS 客戶端可以使用 Java 設(shè)施
          由于 JMS 客戶端是基于 Java 的,因此它們可以利用現(xiàn)有的 Java API,比如:用于數(shù)據(jù)庫(kù)訪問的 JDBC、JavaBeans 組件模型、用于命名服務(wù)的 JNDI、用于客戶端事務(wù)控制的 JTA 或用于企業(yè)應(yīng)用程序服務(wù)的任何 J2SE 和 J2EE API。

          JMS 細(xì)節(jié)
          現(xiàn)在,我們從消息開始,來看一下使用 JMS 構(gòu)建消息傳遞系統(tǒng)客戶端的細(xì)節(jié)。

          什么是消息?
          在消息傳遞系統(tǒng)中,應(yīng)用程序之間的通信點(diǎn)是消息本身,因此使用 JMS 的開發(fā)人員必須理解消息。

          盡管消息傳遞系統(tǒng)之間消息定義區(qū)別甚大,但 JMS 提供了統(tǒng)一的方式用于描述和訪問消息。JMS 消息由三部分組成:

          消息標(biāo)題
          用于消息標(biāo)識(shí)。例如,標(biāo)題用于確定指定的消息是否適合于“訂閱者”。
          屬性
          用于特定于應(yīng)用程序、特定于提供商及可選的標(biāo)題字段。
          消息體
          保存消息的內(nèi)容。支持幾種格式,其中包括:TextMessages——用于包裝簡(jiǎn)單的 String; 和 ObjectMessages——用于包裝任意的 Java 對(duì)象(它們必須是可序列化的)。也支持其他的格式。
          TextMessages
          TextMessage 用于包裝簡(jiǎn)單的 String 對(duì)象。在只傳遞字符串的情形下,這是有用的。期望許多消息傳遞系統(tǒng)將以 XML 為基礎(chǔ),TextMessages 是它們的自然容器。


          創(chuàng)建 TextMessage 對(duì)象是簡(jiǎn)單的,如下面兩行代碼所指出的那樣:

          TextMessage message =
          session.createMessage();
          message.setText("hello world");

          (在下一節(jié),我們將看到 session 對(duì)象)。

          以這種方式創(chuàng)建的 TextMessage 準(zhǔn)備發(fā)布到消息傳遞系統(tǒng)中。

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

          下面展示了如何創(chuàng)建 Object 消息:

          ObjectMessage message = session.createObjectMessage();
          message.setObject(myObject);

          關(guān)于 JNDI
          像許多 J2EE API 一樣,JMS 利用了 JNDI(Java 命名和目錄接口)來發(fā)現(xiàn)所需資源。詳細(xì)討論 JNDI 超出了本文的范圍,但可從如下地址找到更多的進(jìn)一步信息:Java 命名和目錄接口 (JNDI)。

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

          創(chuàng)建到消息傳遞系統(tǒng)提供商的連接。
          創(chuàng)建會(huì)話用于發(fā)送和接收消息。
          創(chuàng)建 MessageProducers 和 MessageConsumers 來創(chuàng)建或接收消息。
          一旦這些步驟執(zhí)行完畢,消息生產(chǎn)的客戶端將創(chuàng)建消息,并把它們發(fā)布到主題,而消息消費(fèi)的客戶端將偵聽與主題有關(guān)的消息,并在它們到達(dá)時(shí)消費(fèi)它們。

          為了詳細(xì)展示它是如何工作的,我們研究了典型的消息生產(chǎn)者,它用于在 pub/sub 消息傳遞系統(tǒng)中把消息發(fā)布到特定的主題。注意,為簡(jiǎn)潔起見,省略了所有異常處理代碼。

          創(chuàng)建連接
          連接為客戶端提供了對(duì)基礎(chǔ)消息傳遞系統(tǒng)的訪問,并執(zhí)行資源分配和管理。連接是使用 ConnectionFactory 創(chuàng)建的,而 ConnectionFactory 通常是使用 JNDI 查找的。

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

          Context messaging = new InitialContext();
          // get JNDI context
          TopicConnectionFactory topicConnectionFactory =
          (TopicConnectionFactory)
          messaging.lookup("TopicConnectionFactory");
          TopicConnection topicConnection =
          topicConnectionFactory.createTopicConnection();


          創(chuàng)建會(huì)話
          會(huì)話是輕量級(jí) JMS 對(duì)象,它提供了用于生產(chǎn)和消費(fèi)消息的上下文。會(huì)話用于生成消息生產(chǎn)者和消息消費(fèi)者,以及用于生成消息本身。

          TopicSession session =
          topicConnection.createTopicSession(false,
          Session.CLIENT_ACKNOWLEDGE);

          createTopicSession() 的兩個(gè)參數(shù)控制事務(wù)和消息的確認(rèn)。

          查找主題
          主題(也稱標(biāo)題、組或頻道)是通過 JNDI 來查找的。主題標(biāo)識(shí)了發(fā)送中或接收中的消息。在發(fā)布/閱系統(tǒng)中,訂閱者訂閱了指定的主題,而發(fā)布者把主題與它們發(fā)布的消息關(guān)聯(lián)。

          這里我們創(chuàng)建了一個(gè)稱為“WeatherData”的主題。

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

          啟動(dòng)連接
          在上面的初始化過程中,為了防止初始化期間出現(xiàn)不可預(yù)知的行為,消息流是被禁止的。一旦初始化完成,必須告訴連接開始消息流。

          topicConnection.start();

          創(chuàng)建消息生產(chǎn)者
          在發(fā)布/訂閱領(lǐng)域中,生產(chǎn)者把消息發(fā)布到指定主題。下面代碼展示了發(fā)布者的創(chuàng)建及后續(xù)的簡(jiǎn)單文本消息的生成和發(fā)布。

          TopicPublisher publisher =
          session.createPublisher(weatherData);
          TextMessage message = session.createMessage();
          message.setText("temperature: 35 degrees");

          publisher.publish(message);


          創(chuàng)建訂閱者及點(diǎn)對(duì)點(diǎn)系統(tǒng)的 JMS 客戶端遵循相似的過程。可以在 [1] 中找到這一過程的完整細(xì)節(jié)。

          結(jié)束語
          我們已經(jīng)看到在使用 JMS 來構(gòu)建基于消息傳遞的應(yīng)用程序的過程中涉及的基本概念。在編寫 JMS 代碼之前,你將需要訪問符合 JMS 的消息傳遞系統(tǒng)。可從如下地址獲取符合 JMS 的供應(yīng)商的列表:


          JMS 供應(yīng)商


          創(chuàng)建和構(gòu)建基于 JMS 的應(yīng)用程序是簡(jiǎn)單的,可是它為構(gòu)建強(qiáng)大、可伸縮和高可靠的分布式系統(tǒng)提供了基礎(chǔ)。

          注意,JMS 遠(yuǎn)遠(yuǎn)比本文討論的要復(fù)雜,并為下面的這些提供了支持:管理、安全、錯(cuò)誤處理和恢復(fù)、優(yōu)化、分布式事務(wù)、消息排序和消息確認(rèn)等。

          有關(guān) Java Message Service 的進(jìn)一步信息和文檔,請(qǐng)參閱:

          Java Message Service 文檔

          參考資料
          本文中的許多內(nèi)容是以 Java Message Service 文檔 為基礎(chǔ)的。

          本文的再版須有 SunServer 許可。

          posted on 2007-04-02 11:06 ASONG 閱讀(428) 評(píng)論(0)  編輯  收藏 所屬分類: JAVA

          主站蜘蛛池模板: 乌鲁木齐县| 靖西县| 集安市| 广东省| 江西省| 双辽市| 易门县| 大同市| 余江县| 荣昌县| 高雄市| 汽车| 阳原县| 荆州市| 于都县| 孝昌县| 淮安市| 漳州市| 舞钢市| 克什克腾旗| 霍山县| 梁山县| 河北省| 天柱县| 七台河市| 繁昌县| 英吉沙县| 丰顺县| 南城县| 甘谷县| 宜兴市| 邻水| 唐山市| 界首市| 冕宁县| 贵阳市| 临潭县| 黄浦区| 龙岩市| 余江县| 睢宁县|