說到對消息傳遞解決方案的選擇,您可以像配手套那樣找到適合於企業的解決方案。您 的消息傳遞框架必須能夠在一組應用和企業資源之間進行通信。而且,該消息傳遞框架必 須快速、可靠地完成這一任務。此外,面對日復一日的騷擾和緊急情況,它必須表現得天 衣無縫。
為了根據您的需求選擇適當的消息傳遞解決方案,首先應該對您企業當前的組成結構以 及將來的發展趨勢有一個清醒的認識。此外,如果能夠透徹地理解消息傳遞框架在完成目 標的過程中必須克服的障礙,那麼對於解決方案的選擇將會很有幫助。最後,您要知道可 選擇的范圍:有哪些可用的技術,以及各種技術對於不同的環境和需求的適用情況如何。
在本期的J2EE 探索者中,我們將一一闡述以上要點。首先是對企業消息傳遞的概述, 在此我們將著眼於消息傳遞在您企業中所扮演的角色,並在建立可靠的通信方面給出了一 些挑戰。接著,我們將從體系結構的角度來快速了解一下,在一個典型的企業網絡環境中 ,J2EE 消息傳遞技術如何與面向消息的中間件協同工作。然後,我們將針對Java消息服務 (Java Message Service ,JMS)和J2EE的消息傳遞包展開更具體的討論。我們將分別論 述三種類型的J2EE消息傳遞客戶機的基本目標和功能,而且您也可以了解到每種類型的 J2EE消息傳遞客戶機各自的優勢和劣勢所在。最後,我們將分析一些常見的消息傳遞場景 和解決方案,這將有助於您為您的企業選擇最好的J2EE消息傳遞解決方案。
企業消息傳遞101
企業消息傳遞框架被設計用於使得一個或多個應用能夠克服各種障礙進行通信。常見的 屏障包括:兩個系統同時運行(同步通信)的需求,多個應用獲取同一條消息(多重傳輸 )的需求,大多數系統都彼此異構,以及網絡故障等。
M許多企業的體系結構依賴於面向消息的中間件系統(MOM)來為不同類型的系統提供消 息通道。MOM為應用提供了一種公共的、可靠的方式,使這些應用能夠輕松地創建、交換和 處理消息,而無需考慮消息傳遞客戶機的實現細節。消息被發送到服務器目的地和域 (domain),而不是發送到物理地址。消息傳遞客戶機只需簡單地聲明對某個特定的域和 目的地感興趣,提供適當的安全性令牌(security token)以獲得訪問該域的權限,然後 通過那個目的地與消息傳遞服務器進行交互。
從概念上來講,這與現實生活中真實郵件的傳遞方式沒什麼不同。消息的發送方只負責 使用正確的包裝,提供正確的地址,並附上適當的郵資。郵局(這裡是一個MOM系統)處理 與消息的安全可靠的傳遞相關的所有問題,而不 管出現在他們面前的任何障礙(機器故障 ,天氣惡劣,等等)。
在一個MOM系統中,客戶機之間的耦合性比較弱,這允許它們不必真正地全天“在線” 便能維持服務的最佳質量。如果能夠去掉應用一直處於可用狀態這一需求,那麼維護和伸 縮性將變得更加易於管理。可以在一天中的任何時候將應用離線,更新應用,或者作為例 行的維護工作刷新應用,而不必擔心會影響服務的質量。
Java 消息服務
MOM 服務器允許不同類型的系統交換消息,但是每個MOM供應商都有其特有的處理消息 的API。這種標准化的缺乏對於Java技術開發范例來說是不可接受的。為了充分利用已有的 MOM基礎設施,同時又不失標准化,J2EE平台提供了JMS。
JMS 定義了在Java企業系統中傳遞消息的規則,並且聲明了一些方便應用組件和消息傳 遞系統(通常是MOM)之間的消息交換的接口。JMS客戶機向MOM服務器上的目的地開放連接 ,然後在那個目的地上發送和接收消息。JMS卸下了保證傳送(guaranteed delivery)、 消息通知(message notification)、消息耐久性(message durability)以及消息傳遞 系統中所有底層網絡和路由問題的負擔。JMS和MOM能夠很好地協同工作,因為它們都劃清 了消息傳遞客戶機和服務器之間的責任界限。
消息傳遞的類型
JMS 支持兩種基本的消息傳遞機制。第一種機制是點到點的消息傳遞(point-to-point messaging),在這種機制下,消息由一個發布者(發送方)發送,由訂閱者(接收方)接 收。另一種機制是發布-訂閱式的消息傳遞(publish-subscribe messaging),在這種機 制下,消息由一個或多個發布者發送,由一個或多個訂閱者接收。盡管這兩種機制是JMS的 實際基礎,很多人還是按照三種消息傳遞模型來看待這項技術:
一對一的消息傳遞(One-to-one messaging )是一種點到點的模型。消息由一個JMS客 戶機(發布者)發送到服務器上的一個目的地,即一個隊列(queue)。而另一個JMS客戶 機(訂閱者)則可以訪問這個隊列,並從該服務器獲取這條消息。在隊列中可以存放多條 消息,但每次只能獲取一條消息。
一對多的消息傳遞(One-to-many messaging) 是一種發布-訂閱模型。這裡仍然是由 一個JMS客戶機將一條消息發布到服務器上的一個目的地上,但是這次這個目的地叫做一個 主題(topic)。這裡關鍵的不同在於放在一個主題中的消息包括了一個參數,這個參數定 義了該消息的耐久性(它能夠在服務器上等待訂閱者多長時間)。該消息將一直維持在主 題中,直到這個主題的所有訂閱者都取走了該消息的一個副本,或者該消息的耐久性時間 已到期,不管發生的是上述中的哪種情況,該消息都將被從這個主題中刪除。
多對多的消息傳遞(Many-to-many messaging),這也是一種發布-訂閱模型,同時還 擴展了一對多的消息傳遞模型。除了支持多個訂閱者外,該模型還支持一個主題有多個發 布者。多對多消息傳遞的一個很好的例子就是e-mail listserve:多個發布者可以將多條 消息投遞到一個主題,而所有的訂閱者將獲取每一條消息。
JMS消息的結構相當直觀。其中有一個部分(section)用於路由、尋址和消息識別;還 有一個可選的部分,在這個部分中可以傳遞一些特定於應用(application-specific)的 參數;第三個部分存放的是消息的有效負荷(文本 、字節、值映射(value map)、對象 ,等等)。這三個部分分別被稱為頭部、屬性和主體,如圖 1 所示。
圖 1. JMS 消息結構
您所使用的消息傳遞模型的類型取決於您企業的需要。在一個企業中同時使用不止一個 的消息傳遞策略並不少見。在後面的一些小節中,我們將研究一下用於Java平台的三種JMS 解決方案:簡單JMS客戶機,結合JMS使用的會話bean,以及消息驅動bean。我們將重新回 顧每種類型,它們各自的優點和缺點,以及它們對不同企業場景的適用情況。
簡單JMS客戶機
盡管JMS是與Java 2 Enterprise Edition一起發布的一種企業級的技術,您仍可以輕松 地將一個標准Java客戶機轉換成一個支持JMS的應用。將企業消息傳遞功能添加到Java applet、命令行應用程序、Swing應用程序或者Java WebStart都非常簡單。您只需簡單地 將少量方法調用添加到J2SE應用代碼中,然後將一個包含了JNDI(也是J2EE的一部分)的 接口和實現類的JAR文件添加到類路徑(classpath)中。如果您已經在客戶機上裝載了這 個JAR文件,並且將它添加到了您的應用的類路徑中,那麼您就可以使用JNDI來訪問JMS提 供者(參見下面的 參考資料 ,以獲得關於JMS消息傳遞的更多信息的鏈接)。
簡單JMS 客戶機的優點和缺點
簡單JMS 客戶機方法有許多優點,最明顯的優點就是它的簡單性和普遍性。所有的J2SE 應用都可以毫不費力地擴展為可以與一個JMS消息傳遞系統進行交互。此外,使用JMS的新 應用部署起來只需對客戶端進行少量的配置,甚至不需要配置。簡單JMS客戶機是對幾乎任 何Java體系結構的簡單、靈活和輕量級的一個擴展。
從消極的方面來看,我們會遇到安全性、事務處理以及可伸縮性等問題。對於一個簡單 JMS客戶機,您只能選擇將安全性和事務處理外包給某個供應商,也就是說,這些問題將是 以一種特定於供應商的方式來處理的。如果您的簡單JMS客戶機既要處理傳進來的消息,又 要發送消息,那麼就會碰到可伸縮性問題。JMS沒有能夠一次處理多於一個傳進來的請求的 內建機制。為了支持並發請求,您需要擴展JMS客戶機,使其產生多個線程,或者啟動多個 JVM實例,讓這些線程或實例各自運行應用。此外,還需要將JMS提供者配置為在一些適當 的目的地上可以有多個訂閱者。這時,您(或者您的開發小組)就會質疑簡單JMS客戶機解 決方案是否真的具有簡單性。
會話bean與JMS
將會話bean與JMS結合起來使用是一種可行的面向企業的解決方案。會話bean被設計用 來履行對業務服務的請求。必須查詢企業消息傳遞系統來履行這樣的一個請求,就這一點 來說,企業消息傳遞系統可以由一個會話bean透明地來訪問。使用會話bean作為JMS客戶機 還允許將JMS通信合並到一個大型企業事務的上下文環境中。例如,可以建立一個J2EE事務 來從一個JMS提供者那裡獲取一條消息,從該消息中提取數據,並嘗試更新數據庫。如果更 新操作失敗並且事務回滾(rollback),則再發送一條消息到一個單獨的目的地上的JMS提 供者那裡,同時給出對事務失敗的原因的描述。
企業JavaBeans 技術使用資源管理器連接工廠來訪問額外容器(extra-container )資 源。這些資源是標准的企業組件,但不是J2EE容器的核心部分,它們包括數據源、JMS會話 、JavaMail會話、URL連接以及Java連接器體系結構( Java Connector Architecture , JCA)適配器。資源管理器是J2EE容器的一個組件,它管理著某一特定類型的資源的整個生 命周期,這些資源包括連接池、事務支持以及實現實際連接所必需的任何網絡協議。
企業bean通過三個步驟來獲得一個JMS會話的連接:通過JNDI查找獲得一個連接工廠引 用,通過工廠引用獲得一個連接,然後以一種常規的JMS的方式使用主題或者隊列連接對象 。因為JMS必須有遵從J2EE規范的應用服務器的支持,因此不再需要附加的庫或者組件。
JMS會話bean 的優點和缺點
將JMS和會話bean結合起來使用,這在企業功能性方面是一個進步,而在簡單性和靈活 性方面卻又是一個退步。通過使用會話bean,應用開發者可以訪問EJB容器所提供的整個范 圍的J2EE功能,包括JNDI、宣告式事務語義、自動並發支持、資源管理、宣告式安全性以 及對諸如實體bean、數據源、JavaMail和JCA適配器之類的企業資源的訪問。從消息傳遞的 立場來看(跟MDB不一樣),會話bean與JMS的聯手並沒有對您的bean所能訪問的主題和隊 列強加任何數量上的限制。
作為增強企業特性的代價,您犧牲了簡單性,客戶機占用空間(client footprint)也 不再像以前那麼小了,而且也沒有了異步性。前兩項損失倒沒什麼好奇怪的,如果您已經 關注探索者系列有一段時間了,那麼您就更能理解這一點。會話bean要求有一個成熟的 J2EE EJB容器,這讓您的開發小組(針對EJB開發而言)和您的整個系統體系結構(針對客 戶機占用空間而言)背上了沉重的包袱。
異步性是使用像JMS這樣的企業消息傳遞技術的主要優勢之一,而且,在取得這一優勢 的同時它並沒有失去什麼。有了JMS,消息傳遞客戶機可以通過提供者發送消息,消息發送 出去之後便可以離線,而讓提供者從容地傳送這條消息。接收消息的客戶機可以周期性地 上線並檢查新的消息,或者也可以設立一個偵聽器組件,令其一直處於在線狀態以等待來 自提供者的消息。會話bean是同步的,因而不能支持“一直在線(always-on)”偵聽器組 件。與前一種客戶機不同,同步的Java客戶機必須調用一個會話bean方法。然後由該會話 bean方法打開與一個消息傳遞提供者的連接,以便發送和接收消息。
消息驅動bean
EJB 2.0 規范定義了一種新的企業bean,以期彌補其他四種類型的企業bean(兩種會話 bean和兩種實體bean)的不足。這種新的bean就是消息驅動bean(message-driven bean, MDB),人們期望用它來提供可重用的消息傳遞組件,以便利用已有的在J2EE應用服務器方 面的投資,尤其是利用已有的EJB技術。
MDB 只能通過一條JMS消息異步地進行調用。因此,它並不具有其他bean所具有的本地 和遠程接口。相反,MDB實現兩種特殊的接口:一個與EJB容器之間的接口 (javax.ejb.MessageDrivenBean),以及一個消息傳遞接口 (javax.jms.MessageListener)。作為一種成熟的JMS客戶機,MDB通過一個MOM服務器既 可以發送消息,又可以接收消息。作為一種企業bean,MDB由容器來管理,並且通過一個 EJB部署描述符進行宣告式的配置。
MDB 的優點和缺點
MDB允許開發者利用已有的在EJB技術方面的投資,但是仍然可以將這些投資整合到一個 異步消息傳遞的上下文環境中。例如,JMS客戶機可以發送一條消息給一個MDB(該MDB一直 在線等待傳進來的消息),而後者可以訪問一個會話bean或者一些實體bean。通過這種方 式,MDB可以被用作一種異步包裝器,提供對業務流程的訪問途徑,而之前這些業務流程只 能通過一個同步的RMI/IIOP調用來訪問。
消息驅動bean本身也是一種強大的消息傳遞解決方案。由於MDB被專門設計用來作為消 息的消費者,並且仍然是由EJB容器管理的,因此它們在可伸縮性方面提供了巨大的優勢。 由於消息bean是無狀態的,並且由容器進行管理,因此它們並發地發送和接收消息(容器 只是簡單地將另一個bean從池中提出)。這一點,加上EJB應用服務器所固有的可伸縮性, 構成了一種極其健壯的、可伸縮的企業消息傳遞解決方案。
另一方面,MDB相對來說還是一種很新鮮的事物,沒有經過很多的檢驗。因而,並不是 所有的J2EE供應商都支持它們,即使是支持MDB的那些供應商也只是最近才實現它們的。可 以預見,MDB的不成熟意味著供應商實現在穩定性和可靠性方面還有一段很長的路要走。而 且,MDB社區也需要經歷更多的錘煉,以獲得一套成形的使用MDB的最佳實踐。
拋開MDB的相對不成熟性不提,理解它是為專門的目的而設計的(即作為JMS消息的消費 者)十分重要。MDB只能通過JMS消息來調用,其他方式都不管用。這意味著它們作為消息 的消費者非常理想,但未必適合作為消息的生產者。消息驅動bean當然可以發送消息,但 前提是它首先要讓一條傳進來的請求調用它。而且,當前設計的MDB只能映射到單個的目的 地。它們只能在那個目的地上偵聽消息。這一限制在以後的版本中可以改變,但目前您只 能為每個您想偵聽的目的地定義一個MDB。
消息傳遞解決方案指導方針
如前所述,選擇適當的解決方案時,大部分要做的工作就是衡量您企業的特定需求,包 括目前的需求和可預見的將來的需求。如果能記住多種企業消息傳遞解決方案可以結合使 用,那麼也會很有幫助。在下一節,我們將看一些常見的消息傳遞場景和每個場景潛在的 JMS解決方案。當您為您的企業選擇適當的消息傳遞技術,或者混合使用多種技術時,這些 內容可以提供一般的指導方針。
從一個組件訪問多個主題和隊列
如果您的業務流程規定了消息目的地只能有條件地訪問(換句話說,如果x<5,則訪 問主題A,如果x>5,則訪問主題B),那麼您將不能使用MDB。不過,您可以使用一個簡 單JMS客戶機,或者將會話bean與JMS結合起來使用。為了在這兩種選擇之間作出決定,您 必須在簡單JMS客戶機的輕量級特性(特別適合於applet、Swing應用程序和獨立的控制台 應用程序)以及J2EE容器的健壯性(包括透明的事務性支持、宣告式安全性和其他EJB型資 源管理功能)之間進行權衡。
異步地訪問會話bean和實體bean
有兩種方式來處理這一場景。比較明顯的一種方式就是使用一個消息驅動bean,但前提 是您的供應商支持MDB技術。MDB被設計用來 消費異步消息並代表消息發送方訪問企業功能 性。此外,應用服務器可以維護一個MDB的多個實例,來處理並發的服務請求。如果您不能 使用MDB,您可以創建一個簡單JMS客戶機,以此來作為一個偵聽器。當收到一條消息時, 該客戶機便可以與應用服務器建立一個同步的RMI連接,並按照常規的方式調用會話bean或 者實體bean。不過,MDB是更值得推薦的解決方案。
構建盡可能瘦的JMS客戶機
在這一方面,簡單JMS客戶機顯然是贏家。如果對您來說更重要的是提供一個輕量級的 消息傳遞客戶機,而不是擁有像會話bean這樣的J2EE客戶機的可伸縮性和健壯性,那麼簡 單JMS是正確的選擇。無論是會話bean與JMS的組合,還是MDB,兩者都需要一個J2EE應用服 務器,這使得兩種選擇都不適合瘦客戶機實現。
並發地發送和接收消息
這裡惟一合適的選擇是使用消息驅動bean。消息驅動bean是專門為這一場景量身定做的 。從技術上講,簡單JMS客戶機也可以利用多線程技術來提供類似的支持,但這種解決方案 開發起來很復雜,並且最後開發出來的東西並沒有很好的可伸縮性。
將消息傳遞合並到J2EE過程中
您或許已經在J2EE體系結構中有所投入,並且認識到將企業消息傳遞合並到這些J2EE過 程中的需要。在大多數情況下,您最好的解決方案是將會話bean與JMS資源連接結合起來使 用。您可以采用已有的會話bean來訪問一個或多個主題和隊列,而不必重建整個基礎設施 。這些會話bean將繼續履行傳統的對業務服務的請求,並且還擔負起了消息傳遞的任務。 在某些情況下,將您已有的業務服務暴露給一個JMS客戶機是有好處的,這從前面的討論中 也可以發現。
結束語
就今天技術前景的多樣性和日趨於異步的特點來說,消息傳遞是一種激動人心的、日益 流行的解決方案。Java 消息服務提供了一種獨立於 供應商和平台的媒介,通過使用企業 消息傳遞將多個系統系在一起。在本文中,我們簡要地浏覽了企業消息傳遞和JMS,並且給 出了一些指導方針,以方便您選擇最適合您企業的解決方案。