002_JMS
1. JMS即Java消息服務(Java Message Service)應用程序接口, 是一個Java平臺中關于面向消息中間件(Message Oriented Middleware)的API, 用于在兩個應用程序之間或分布式系統(tǒng)中發(fā)送消息, 進行異步通信。
2. JMS是一種與廠商無關的API, 它類似于JDBC(Java Database Connectivity)。這里JDBC是可以用來訪問許多不同種類的關系型數(shù)據(jù)庫的API, 而JMS可以訪問包括IBM提供的MQSeries和apache提供的ActiveMQ等許多廠商提供的消息收發(fā)服務。
3. JMS應用程序由以下部分組成
3.1. JMS提供者是一個消息系統(tǒng), 實現(xiàn)了JMS接口并提供管理和控制功能。(例如: ActiveMQ)
3.2. JMS客戶端是用Java編程語言編寫的程序或組件, 它們可以生成和使用消息。
3.3. 管理對象是管理員為客戶端使用而創(chuàng)建的預配置JMS對象。有兩種JMS管理對象, 分別是目的地和連接工廠。
3.4. 消息是在JMS客戶端之間傳遞信息的對象。
3.5. JMS生產者, 創(chuàng)建并發(fā)送消息的JMS客戶。
3.6. JMS消費者, 接收消息的JMS客戶。
3.7. 點對點消息傳遞域, 一個容納那些被發(fā)送的等待被閱讀的消息的隊列。與隊列名字所暗示的意思不同, 消息的接受順序并不一定要與消息的發(fā)送順序相同。一旦一個消息被閱讀, 該消息將被從隊列中移走。
3.8. 發(fā)布/訂閱消息域(JMS主題), 一種支持發(fā)送消息給多個訂閱者的機制。
4. 點對點消息模型
4.1. 點對點模型用于消息生產者和消息消費者之間的通信。在點對點消息傳送模型中, 應用程序由消息隊列(Queue)、生產者(Producer)和消費者(Consumer)組成。消息生產者將消息發(fā)送到由某個特定名字標示的消息隊列(Queue)中, 消息消費者從這個特定隊列中獲取對應消息。隊列保留發(fā)送給它的所有消息, 直到消息被消耗或過期。
4.2. PTP消息傳遞具有以下特征
4.2.1. 每條消息只有一個使用者。
4.2.2. 消息的發(fā)送者和接收者沒有時間依賴性。也就是說, 當發(fā)送者發(fā)送了消息時, 不管接收者有沒有正在運行, 它不會影響消息被發(fā)送到消息隊列中。同時, 接收者接收消息的時候, 發(fā)送者也不必同時運行。
4.2.3. 當接收者收到消息的時候, 會發(fā)送確認收到通知(acknowledgement)到消息隊列。
4.3. 模型圖
5. 發(fā)布訂閱消息模型
5.1. 在發(fā)布與訂閱消息傳送模型中, 應用程序由主題(Topic)、發(fā)布者(Publisher)和訂閱者(Subscriber)組成。在這種模型中, 發(fā)布者和訂閱者通常是匿名的, 且可以動態(tài)發(fā)布和訂閱主題(Topic)。該系統(tǒng)負責將主題的多個發(fā)布者送達的消息分發(fā)到其多個訂閱者。主題僅保留將消息分發(fā)給當前訂閱者所需的時間。
5.2. 發(fā)布/訂閱消息傳遞具有以下特征
5.2.1. 每個消息可以有多個使用者。
5.2.2. 發(fā)布者和訂閱者具有時間依賴性。針對某個主題(Topic)的訂閱者, 它必須創(chuàng)建一個訂閱者之后, 才能消費發(fā)布者的消息, 而且為了消費消息, 訂閱者必須保持運行的狀態(tài)。
5.2.3. 為了緩和這樣嚴格的時間依賴性, JMS允許訂閱者創(chuàng)建一個可持久化的訂閱。這樣, 即使訂閱者沒有在運行狀態(tài), 它也能在再次運行的時候接收到發(fā)布者的消息。
5.3. 模型圖
6. JMS的消息消費
6.1. 消息產品本質上是異步的, 消息的產生和消費之間沒有基本的時序依賴性。但是, JMS規(guī)范在更精確的意義上使用了該術語。可以通過以下兩種方式之一來使用消息:
6.1.1. 同步: 通過調用消費者的receive方法從目的地顯式的提取消息, receive方法在接收到消息之前或超時之前將一直阻塞。
6.1.2. 異步: 客戶端可以向使用者注冊消息偵聽器。消息監(jiān)聽器類似于事件偵聽器。每當消息到達目的地時, JMS提供程序都會通過調用監(jiān)聽器的onMessage方法來傳遞消息, 客戶端不必請求消息即可接收它們, 該方法將對消息的內容進行操作。
7. 連接工廠是用來創(chuàng)建客戶和提供者之間的連接。連接工廠封裝了一組由管理員定義的連接配置參數(shù)。每個連接工廠都是ConnectionFactory、QueueConnectionFactory或TopicConnectionFactory接口的實例。
8. JMS連接
8.1.?Connection表示在客戶端和JMS提供者之間建立的連接。跟ConnectionFactory一樣, Connection也有QueueConnection和TopicConnection兩種類型的對象。
8.2. 每個連接都是Connection、QueueConnection或TopicConnection接口的實例。當您有一個ConnectionFactory對象時, 可以使用它來創(chuàng)建一個連接。
Connection connection = connectionFactory.createConnection(); QueueConnection connection = connectionFactory.createQueueConnection(); TopicConnection connection = connectionFactory.createTopicConnection();8.3. 在應用程序完成之前,必須關閉所有已創(chuàng)建的連接。沒有關閉連接可能導致JMS提供程序無法釋放資源。關閉連接也會關閉其會話以及它們的消息產生者和消息使用者。
connection.close();8.4. 在您的應用程序可以使用消息之前, 您必須調用連接的start方法。
connection.start();9. JMS會話
9.1. JMS會話(Session)是用于制造和使用消息的單線程上下文。同樣, Session也有QueueSession和TopicSession兩種類型的對象。
9.2. 您使用會話創(chuàng)建以下內容:
9.2.1. 消息生產者
9.2.2. 消息消費者
9.2.3. 消息內容
9.2.4. 隊列瀏覽器
9.2.5. 臨時隊列和主題
9.3. 會話可以提供了一個事務上下文, 在該上下文中, 一組發(fā)送和接收被組合到了一個原子操作中。
9.4. 創(chuàng)建Connection對象后, 可以使用它來創(chuàng)建Session,?第一個參數(shù)表示會話未使用事務; 第二種參數(shù)是會話在成功接收到消息后會自動對其進行確認。
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);9.5. 要創(chuàng)建事務會話, 請使用以下代碼,?第一個參數(shù)表示會話使用事務; 第二個參數(shù)指示未為事務會話指定消息確認。第二個參數(shù)是Session.SESSION_TRANSACTED時, 第一個參數(shù)必須是true。
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);9.6. JMS的可靠性機制?
9.6.1. JMS消息只有在被確認之后, 才認為已經被成功地消費了。消息的成功消費通常包含三個階段: 客戶接收消息、客戶處理消息和消息被確認。
9.6.2. 在事務性會話中, 當一個事務被提交的時候, 確認自動發(fā)生。在非事務性會話中, 消息何時被確認取決于創(chuàng)建會話時的應答模式(acknowledgement mode)。
9.6.3. 該參數(shù)有以下三個可選值
- Session.AUTO_ACKNOWLEDGE: 當客戶成功的從receive方法返回的時候或者從MessageListener.onMessage方法成功返回的時候, 會話自動確認客戶收到的消息。
- Session.CLIENT_ACKNOWLEDGE: 客戶主動給的調用消息的acknowledge方法確認消息。需要注意的是, 在這種模式中, 確認是在會話層上進行。確認一個被消費的消息將自動確認所有已被會話消費的消息。例如, 如果一個消息消費者消費了10個消息, 然后確認第5個消息, 那么所有10個消息都被確認。
- Session.DUPS_OK_ACKNOWLEDGE: 該選擇只是會話延遲的確認消息的提交。如果JMS provider失敗, 那么可能會導致一些重復的消息。不過使用此種模式, 可以減輕會話的負載。
10. 消息目的地(Destination), 即消息生產者的消息發(fā)送目標或者說消息消費者的消息來源。在PTP消息傳遞域中, 目的地稱為隊列。在發(fā)布/訂閱消息傳遞域中, 目的地稱為主題。 同樣, Destination也有Queue和Topic兩種類型的對象。
11. 消息生產者
11.1. 消息生產者(MessageProducer), 由Session創(chuàng)建, 并用于將消息發(fā)送到目的地。同樣, MessageProducer也有QueueSender和TopicPublisher兩種類型的對象。
11.2. 使用會話為目的地創(chuàng)建生產者。以下示例說明您可以為Destination、Queue或Topic對象創(chuàng)建生產者。
MessageProducer messageProducer = session.createProducer(dest); QueueSender sender = session.createSender(queue); TopicPublisher publisher = session.createPublisher(topic);11.3. 可以通過將null指定為createProducer的參數(shù)來創(chuàng)建身份不明的生產者。對于身份不明的生產者, 在發(fā)送消息的時候指定目的地。
MessageProducer messageProducer = session.createProducer(null);11.4. 創(chuàng)建消息產生器之后, 可以使用send方法發(fā)送消息
MessageProducer nonDesProducer = session.createProducer(null); nonDesProducer.send(destination, message); MessageProducer producer = session.createProducer(destination); producer.send(message);12. 消息消費者
12.1. 消息消費者(MessageConsumer), 由Session創(chuàng)建, 用于接收目的地的消息。MessageConsumer也有QueueReceiver和TopicSubscriber兩種類型的對象。
12.2. 可以使用Session為MessageConsumer、Queue或Topic對象創(chuàng)建消息消費者。
MessageConsumer messageConsumer = session.createConsumer(dest); QueueReceiver receiver = session.createReceiver(queue); TopicSubscriber subscriber = session.createSubscriber(topic);12.3. 可以通過session的creatDurableSubscriber方法來創(chuàng)建持久化的訂閱者。僅當您使用主題時, 此方法才有效。
13. 消息偵聽器
13.1.?消息偵聽器是充當消息的異步事件處理程序的對象。此對象實現(xiàn)MessageListener接口, 該接口包含一個方法onMessage。在onMessage方法中, 消息到達時要執(zhí)行的操作。
13.2.?您可以使用setMessageListener方法向特定的MessageConsumer注冊消息偵聽器。
MessageConsumer consumer = session.createConsumer(destination); consumer.setMessageListener(new MessageListener() {@Overridepublic void onMessage(Message msg) {} });13.3.?注冊消息偵聽器后, 您可以在Connection上調用start方法以開始傳遞消息。如果在注冊消息偵聽器之前調用start, 則可能會丟失消息。
13.4.?每當傳遞消息時, JMS提供程序都會自動調用消息偵聽器的onMessage方法。onMessage方法采用一個Message類型的參數(shù)消息, 其可以轉換為其它真實類型的消息。
13.5.?消息偵聽器并不僅僅監(jiān)聽一個特定類型的目標。同一偵聽器可以從隊列或主題中獲取消息, 具體取決于為其創(chuàng)建消息使用者的目的地的類型。但是, 消息偵聽器通常期望特定的消息類型和格式。
13.6.?您的onMessage方法應處理所有異常, 如果拋出RuntimeException被認為是編程錯誤。
14. JMS消息選擇器
14.1. 如果您的消息傳遞應用程序需要過濾接收到的消息, 則可以使用JMS API消息選擇器, 該消息選擇器允許消息使用者指定對其感興趣的消息。消息選擇器將過濾消息的工作分配給JMS提供程序而不是應用程序。
14.2. 消息選擇器是一個包含表達式的字符串。表達式的語法基于SQL92條件表達式語法的子集。
14.3. 創(chuàng)建消息使用者時, 可以使用createConsumer和createDurableSubscriber方法將消息選擇器指定為參數(shù)。
14.4. 消息使用者僅接收其消息頭或屬性與選擇器匹配的消息。消息選擇器無法根據(jù)消息正文的內容選擇消息。
15. JMS消息
15.1. JMS應用程序的最終目的是生成和使用消息, 然后其他軟件應用程序可以使用這些消息。JMS消息具有簡單但高度靈活的基本格式, 允許您創(chuàng)建在各個平臺上的非JMS應用程序所使用的格式匹配的消息。
15.2. JMS消息可以包含三個部分: 消息頭, 屬性和主體。僅消息頭是必需的。
15.3. 消息頭(必須)
15.3.1. JMS消息頭包含許多預定義的字段, 這些字段包含客戶端和提供者用來標識和路由消息的值。
15.3.2. 每個消息頭字段都具有關聯(lián)的setter和getter方法, 這些方法記錄在Message接口的說明中。某些消息頭字段旨在由客戶端設置, 但許多消息頭字段由send或publish方法自動設置, 這會覆蓋任何客戶端設置的值。
15.3.3. JMSDestination: 消息發(fā)送的目的地, 主要是指Queue和Topic, 該字段由生產者的send或publish方法設置。
15.3.4. JMSDeliveryMode: 傳送模式, 有持久模式和非持久模式兩種, 默認是持久化消息。一條持久性的消息, 當JMS提供者出現(xiàn)故障時, 該消息并不會丟失, 它會在服務器恢復之后可以重新傳遞。一條非持久的消息, 當服務器出現(xiàn)故障時, 該消息將永遠丟失。該字段由生產者的send或publish方法設置。
15.3.5. JMSExpiration: 消息的過期時間, 是send或publish方法中的timeToLive值加上發(fā)送時刻的GMT時間值的和。如果timeToLive值等于零, 則JMSExpiration被設置為零, 表示該消息永不過期, 默認就是永久不過期。如果發(fā)送后, 在消息過期時間之后消息還沒有被消費, 則該消息被清除。該字段由send或publish方法設置。
15.3.6. JMSPriority: 消息優(yōu)先級, 從0-9十個級別, 0-4是普通消息, 5-9是加急消息。JMS不要求JMS Provider嚴格按照這十個優(yōu)先級發(fā)送消息, 但必須保證加急消息要先于普通消息到達, 默認是4級。該字段由send或publish方法設置。
15.3.7. JMSMessageID: 唯一識別每個消息的標識, 該字段由生產者的send或publish方法設置。
15.3.8. JMSTimestamp: 它是消息被發(fā)送給提供者的時間。該字段由生產者的send或publish方法自動設置。
15.3.9. JMSCorrelationID: 用來連接到另外一個消息, 典型的應用是在回復消息中連接到原消息。在大多數(shù)情況下, JMSCorrelationID用于將一條消息標記為對JMSMessageID標示的上一條消息的應答, 不過, JMSCorrelationID可以是任何值, 不僅僅是JMSMessageID。該字段由客戶端設置。
15.3.10. JMSReplyTo: 提供本消息回復消息的目的地址。該字段由客戶端設置。
15.3.11. JMSType: 消息類型的標識符, JMS API并沒有定義該字段的一個標準, 可以根據(jù)應用程序的實際需求設計該字段, 來標識應用程序是否使用該類型的消息。該字段由客戶端設置。
15.3.12. JMSRedelivered: 如果一個客戶端收到一個設置了JMSRedelivered屬性的消息, 則表示可能客戶端曾經在早些時候收到過該消息, 但并沒有簽收(acknowledged)。如果該消息被重新傳送, JMSRedelivered=true否則JMSRedelivered=flase。該字段由提供者設置。
15.4. 消息頭的這些字段, 我們可以按照需求對它進行設計, 再使用生產者的send或publish方法將其發(fā)送到消息服務上。
16. 消息屬性(可選): 如果您需要除消息頭字段提供的值以外的其它值, 則可以創(chuàng)建和設置消息的屬性。您可以使用屬性來提供與其它消息傳遞系統(tǒng)的兼容性, 也可以使用它們來創(chuàng)建消息的選擇器。
17. 消息體(可選): 允許用戶創(chuàng)建五種類型的消息: TextMessage(文本消息)、MapMessage(映射消息)、BytesMessage(字節(jié)消息)、StreamMessage(流消息)和(ObjectMessage)對象消息。消息接口非常靈活, 并提供了許多方式來定制消息的內容。
總結
- 上一篇: 001_消息中间件
- 下一篇: 003_ActiveMQ管理后台