JMS是一種企業消息傳送的API,並不是MOM消息中間件系統的全部,JMS也是一種規範,類似於JDBC,我們通JMS API訪問 JMS的服務器。目前JMS服務器的主要產品有 IBM WebSphere MQ、SonicMQ、Sun Open MQ、BEA WebLogic JMS、Oracle AQ 以及 我們最常用的JBoss MQ 和 Apache的 ActiveMQ.。而JMS服務器是MQ(Message Queen)產品家族中的一種,Microsoft Message Queuing(mSMQ)也是MQ產品類似於JMS服務器。
JMS在J2EE系統中的應用場景
異步消息比同步消息操作更加便利。在J2EE系統中最常見的一個場景,前端瀏覽器 jsp/servlet向服務器端發出一個請求,jsp/servlet將請求傳遞給後端的應用程序處理業務邏輯,業務模塊將響應的結果直接返回給客戶端,而不是真正的計算結果,例如一個網站的用戶註冊功能,一個用戶點擊註冊以後,將會發送一份郵件給他當時的註冊郵箱,如果需要等到郵件發送成功再返回給用戶結果的話,用戶體驗將會很差,所以將結果直接返回給用戶,將用戶註冊的信息通過消息發送給後端程序慢慢處理。
談到 JMS一詞 大體上有 3個部分 1 消息發送端 2中間件服務器 3消息接收端 3個組件缺一不可。 JMS消息分爲兩種消息模式,點對點和發佈者/訂閱者。許多提供商支持這一因此,程序員可以在他們的分佈式軟件中實現面向消息的操作,這些操作將具有不同面向消息中間件產品的可移植性。
Java消息服務器是指,將數據通過消息作爲載體在網絡中從一個系統異步傳送給另一個系統。這樣的異步消息傳送意味着:發送者不需要等待接收者接收或處理該消息;它可以自由地發送消息並持續進行處理。這樣一個異步式的架構主要依賴於一臺消息服務器(message server)。消息服務器,也稱爲消息路由器(message router)或代理(broker),它負責從一個消息傳送客戶端向其他消息傳送客戶端傳送消息。
JMS對與一個大型系統是必不可少的一個應用組件,可以利用JMS來實現3個目的:
1.提高可伸縮性(Increase Scalability),
2.可以利用JMS來緩解系統瓶頸(Reduce Bottlenecks)
3.提高系統對用戶的響應能力
JMS公共API內部,和發送和接收JMS消息有關的JMS API接口常用的有7個:
·ConnectionFactory
·Destination
·Connection
·Session
·Message
·MessageProducer
·MessageConsumer
其中關鍵的5個部件,如圖所示:
查看大圖請點擊這裏
Topic與Queue消息的區別
Queue是一對一的消息傳送,你可以看做是QQ應用程序中的一對一發送消息,一個人發出消息,只能有另外一個人閱讀的到,中間需要通過一個隊列支持Queue消息發送完畢後會保存在 JMS服務器的隊列中,如果接收端接收以後將從隊列中摘除。如圖所示:
Queue消息發送到服務器,接收端會平均接收到發送端發送過來的消息,如圖所示,一次發送150個消息,3個接收端每個收到50個
Topic 是一對多的消息傳送,你可以看做是QQ應用程序 QQ羣 聊天中的一對多發送消息,一個人發出消息,可以有多個訂閱的人閱讀的到,需要有一個消息主題作爲支柱,Tocip消息發送完畢以後 無論有沒有客戶端接收,JMS服務器中的Topic消息都不會存在JMS服務器中。如圖所示:
發送Topic消息無論連接在JMS服務器上有多少個接收端,將會收到同樣的消息,而且Topic發送完畢以後不會保留在JMS服務器,否則將會和Topic消息的設計思想相互衝突。
JMS消息的屬性
JMS的每條消息分爲 Header、Properties 、Body 3個屬性 :
Header、Properties 中包含可設置的參數,分別是:
JMSDestination 消息發送的目的地
JMSDeliveryMode 傳遞模式, 有兩種模式: PERSISTENT 和NON_PERSISTENT,PERSISTENT 表示該消息一定要被送到目的地,否則會導致應用錯誤。NON_PERSISTENT 表示偶然丟失該消息是被允許的,這兩種模式使開發者可以在消息傳遞的可靠性和吞吐量之間找到平衡點。
JMSMessageID 唯一識別每個消息的標識,由JMS Provider 產生。
JMSTimestamp 一個消息被提交給JMS Provider 到消息被髮出的時間。
JMSCorrelationID 用來連接到另外一個消息,典型的應用是在回覆消息中連接到原消息。
JMSReplyTo 提供本消息回覆消息的目的地址
JMSRedelivered 如果一個客戶端收到一個設置了JMSRedelivered 屬性的消息,則表示可能該客戶端曾經在早些時候收到過該消息,但並沒有簽收(acknowledged)。
JMSType 消息類型的識別符。
JMSExpiration 消息過期時間,等於QueueSender 的send 方法中的timeToLive 值或TopicPublisher 的publish 方法中的timeToLive 值加上發送時刻的GMT 時間值。如果timeToLive值等於零,則JMSExpiration 被設爲零,表示該消息永不過期。如果發送後,在消息過期時間之後消息還沒有被髮送到目的地,則該消息被清除。
JMSPriority 消息優先級,從0-9 十個級別,0-4 是普通消息,5-9 是加急消息。JMS 不要求JMS Provider 嚴格按照這十個優先級發送消息,但必須保證加急消息要先於普通消息到達。
Body 分爲以下5種:
TextMessage
這種類型攜帶了一個java.lang.String作爲有效負載。它可以用於簡單的文本消息交換,還可以用於更復雜的字符數據交換,比如XML文檔等。
ObjectMessage
這種類型攜帶了一個可序列化Java對象作爲有效負載。它可以用於Java對象交換。
BytesMessage
這種類型攜帶了一組原始類型字節流(primitive byte)作爲有效負載。它可以使用應用程序的本機格式(native format)來交換數據,這種格式可能不兼容其他現有的Message類型。當JMS純粹用於兩個系統之間的消息傳送時,也可以使用這種類型,而且該消 息的有效負載對JMS客戶端來說是不透明的。
StreamMessage
這種類型攜帶了一個Java原始數據類型流(int、double、char等)作爲有效負載。它提供了一套將格式化字節流映射爲Java原始數據類型的簡便方法。在以固定順序進行原始應用數據交換時,這種模型非常易於編程實現。
MapMessage
這種類型攜帶了一組名/值對(name-value pair)作爲有效負載。有效負載類似於一個java.util.Properties對象,除了有效負載值必須是Java原始數據類型或它們的包裝器之外。MapMessage可以用於傳送鍵入的數據。
JMS的消息存儲
基於內存 最快
基於文件 最慢
基於數據庫 比較慢
JMS的消息過濾功能
這裏selector是一個字符串,用來過濾消息。也就是說,這種方式可 以創建一個可以只接收特定消息的一個消費者。Selector的格式是類似於SQL-92的一種語法。可以用來比較消息頭信息和屬性。例如:發送消息屬性中指定ip地址位數是奇數的接收,而ip地址位數是偶數的絕對不會接收到消息,具體實現方法請Google
關鍵字“jms selector”
JMS消息的順序
亂序接收,順序處理。也就是說,消息在發送,傳輸和接收過程中可能是亂序的,但消費者在接收到消息之後,並不立即處理,而是先將消息排序,然後在處理。 JMS消息頭部的 JMSCorrelationID可以幫助我們完成這個工作。JMSCorrelationID存放了另一個消息的id。消息的發送者,如果要保證消息的順序性,要將後發送的消息的JMSCorrelationID設置成前一個消息的id。消費者接收消息後,如果發現其頭部有 JMSCorrelationID,則查看該消息是否已被處理過,如果沒有,則等待該消息,至到該消息被處理後,才處理這個消息。這一工作需要發送者和接收者都記住已經發送和接收過的消息,以便於給後來的消息參考。由此可見,在JMS中設置JMS的head還是能起到不少作用的。
口水:
本文圖繪採用國產軟件 《億圖圖示專家》所繪製,感謝《億圖圖示專家》的所有開發人員製造出這麼好的工具。