1. 程式人生 > 程式設計 >Java訊息佇列JMS實現原理解析

Java訊息佇列JMS實現原理解析

一、什麼是JMS

JMS即Java訊息服務(Java Message Service)應用程式介面,是一個Java平臺中關於面向訊息中介軟體(MOM)的API,用於在兩個應用程式之間,或分散式系統中傳送訊息,進行非同步通訊。Java訊息服務是一個與具體平臺無關的API,絕大多數MOM提供商都對JMS提供支援(百度百科給出的概述)。我們可以簡單的理解:兩個應用程式之間需要進行通訊,我們使用一個JMS服務,進行中間的轉發,通過JMS 的使用,我們可以解除兩個程式之間的耦合。

二、為什麼需要JMS

在JAVA中,如果兩個應用程式之間對各自都不瞭解,甚至這兩個程式可能部署在不同的大洲上,那麼它們之間如何傳送訊息呢?舉個例子,一個應用程式A部署在印度,另一個應用程式部署在美國,然後每當A觸發某件事後,B想從A獲取一些更新資訊。當然,也有可能不止一個B對A的更新資訊感興趣,可能會有N個類似B的應用程式想從A中獲取更新的資訊。

  在這種情況下,JAVA提供了最佳的解決方案-JMS,完美解決了上面討論的問題。

  JMS同樣適用於基於事件的應用程式,如聊天服務,它需要一種釋出事件機制向所有與伺服器連線的客戶端傳送訊息。JMS與RMI不同,傳送訊息的時候,接收者不需要線上。伺服器傳送了訊息,然後就不管了;等到客戶端上線的時候,能保證接收到伺服器傳送的訊息。這是一個很強大的解決方案,能處理當今世界很多普遍問題。

三、JMS的優勢

1、非同步

JMS天生就是非同步的,客戶端獲取訊息的時候,不需要主動傳送請求,訊息會自動傳送給可用的客戶端。

2、可靠

JMS保證訊息只會遞送一次。大家都遇到過重複建立訊息問題,而JMS能幫你避免該問題。

四、JMS的訊息模型

JMS具有兩種通訊模式:

1、Point-to-Point Messaging Domain (點對點)

2、Publish/Subscribe Messaging Domain (釋出/訂閱模式)

在JMS API出現之前,大部分產品使用“點對點”和“釋出/訂閱”中的任一方式來進行訊息通訊。JMS定義了這兩種訊息傳送模型的規範,它們相互獨立。任何JMS的提供者可以實現其中的一種或兩種模型,這是它們自己的選擇。JMS規範提供了通用介面保證我們基於JMS API編寫的程式適用於任何一種模型。

1、Point-to-Point Messaging Domain(點對點通訊模型)

點對點的模式主要建立在一個佇列上面,當連線一個列隊的時候,傳送端不需要知道接收端是否正在接收,可以直接向ActiveMQ傳送訊息,傳送的訊息,將會先進入佇列中,如果有接收端在監聽,則會發向接收端,如果沒有接收端接收,則會儲存在activemq伺服器,直到接收端接收訊息,點對點的訊息模式可以有多個傳送端,多個接收端,但是一條訊息,只會被一個接收端給接收到,哪個接收端先連上ActiveMQ,則會先接收到,而後來的接收端則接收不到那條訊息。

在點對點訊息傳送模型中,應用程式由訊息佇列,傳送者,接收者組成。每一個訊息傳送給一個特殊的訊息佇列,該佇列儲存了所有傳送給它的訊息(除了被接收者消費掉的和過期的訊息)。

(1)模式圖:

Java訊息佇列JMS實現原理解析

(2)特點:

每個訊息只有一個消費者;

傳送者和接收者在時間上是沒有時間的約束,也就是說傳送者在傳送完訊息之後,不管接收者有沒有接受訊息,都不會影響傳送方傳送訊息到訊息佇列中;

傳送方不管是否在傳送訊息,接收方都可以從訊息佇列中取到訊息;

接收方在接收完訊息之後,需要向訊息佇列應答成功。

2、Publish/Subscribe Messaging Domain(釋出/訂閱通訊模型)

訂閱/釋出模式,同樣可以有著多個傳送端與多個接收端,但是接收端與傳送端存在時間上的依賴,就是如果傳送端傳送訊息的時候,接收端並沒有監聽訊息,那麼ActiveMQ將不會儲存訊息,將會認為訊息已經發送,換一種說法,就是傳送端傳送訊息的時候,接收端不線上,是接收不到訊息的,哪怕以後監聽訊息,同樣也是接收不到的。這個模式還有一個特點,那就是,傳送端傳送的訊息,將會被所有的接收端給接收到,不類似點對點,一條訊息只會被一個接收端給接收到。

在釋出/訂閱訊息模型中,釋出者釋出一個訊息,該訊息通過topic傳遞給所有的客戶端。該模式下,釋出者與訂閱者都是匿名的,即釋出者與訂閱者都不知道對方是誰。並且可以動態的釋出與訂閱Topic。Topic主要用於儲存和傳遞訊息,且會一直儲存訊息直到訊息被傳遞給客戶端。

(1)模式圖:

Java訊息佇列JMS實現原理解析

(2)特點:

一個訊息可以傳遞個多個訂閱者(即:一個訊息可以有多個接收方);

釋出者與訂閱者具有時間約束,針對某個主題(Topic)的訂閱者,它必須建立一個訂閱者之後,才能消費釋出者的訊息,而且為了消費訊息,訂閱者必須保持執行的狀態;

為了緩和這樣嚴格的時間相關性,JMS允許訂閱者建立一個可持久化的訂閱。這樣,即使訂閱者沒有被啟用(執行),它也能接收到釋出者的訊息。

五、JMS接收訊息

在JMS中,訊息的接收可以使用以下兩種方式:

(1)同步

使用同步方式接收訊息的話,訊息訂閱者呼叫receive()方法。在receive()中,訊息未到達或在到達指定時間之前,方法會阻塞,直到訊息可用。

(2)非同步

使用非同步方式接收訊息的話,訊息訂閱者需註冊一個訊息監聽者,類似於事件監聽器,只要訊息到達,JMS服務提供者會通過呼叫監聽器的onMessage()遞送訊息。

六、JMS程式設計模型

(1)管理物件(Administered objects)-連線工廠(Connection Factories)和目的地(Destination)

(2)連線物件(Connections)

(3)會話(Sessions)

(4)訊息生產者(Message Producers)

(5)訊息消費者(Message Consumers)

(6)訊息監聽者(Message Listeners)

Java訊息佇列JMS實現原理解析

(1)JMS管理物件

管理物件(Administered objects)是預先配置的JMS物件,由系統管理員為使用JMS的客戶端建立,主要有兩個被管理的物件:

連線工廠(ConnectionFactory)目的地(Destination)

這兩個管理物件由JMS系統管理員通過使用Application Server管理控制檯建立,儲存在應用程式伺服器的JNDI名字空間或JNDI登錄檔。

① 連線工廠(ConnectionFactory)

建立Connection物件的工廠,針對兩種不同的jms訊息模型,分別有QueueConnectionFactory和TopicConnectionFactory兩種。可以通過JNDI來查詢ConnectionFactory物件。客戶端使用一個連線工廠物件連線到JMS服務提供者,它建立了JMS服務提供者和客戶端之間的連線。JMS客戶端(如傳送者或接受者)會在JNDI名字空間中搜索並獲取該連線。使用該連線,客戶端能夠與目的地通訊,往佇列或話題傳送/接收訊息。讓我們用一個例子來理解如何傳送訊息:

QueueConnectionFactory queueConnFactory = (QueueConnectionFactory) initialCtx.lookup ("primaryQCF");
Queue purchaseQueue = (Queue) initialCtx.lookup ("Purchase_Queue");
Queue returnQueue = (Queue) initialCtx.lookup ("Return_Queue");

② 目的地(Destination)

目的地指明訊息被髮送的目的地以及客戶端接收訊息的來源。JMS使用兩種目的地,佇列和話題。如下程式碼指定了一個佇列和話題。

建立一個佇列Session

QueueSession ses = con.createQueueSession (false,Session.AUTO_ACKNOWLEDGE); //get the Queue object
Queue t = (Queue) ctx.lookup ("myQueue"); //create QueueReceiver
QueueReceiver receiver = ses.createReceiver(t);

建立一個話題

TopicSession ses = con.createTopicSession (false,Session.AUTO_ACKNOWLEDGE); // get the Topic object
Topic t = (Topic) ctx.lookup ("myTopic"); //create TopicSubscriber
TopicSubscriber receiver = ses.createSubscriber(t);

(2)JMS連線物件(Connection)

Connection表示在客戶端和JMS系統之間建立的連線(對TCP/IP socket的包裝)。Connection可以產生一個或多個Session。跟ConnectionFactory一樣,Connection也有兩種型別:QueueConnection和TopicConnection。

連線物件封裝了與JMS提供者之間的虛擬連線,如果我們有一個ConnectionFactory物件,可以使用它來建立一個連線。

Connection connection = connectionFactory.createConnection();

建立完連線後,需要在程式使用結束後關閉它:connection.close();

(3)JMS會話(Session)

Session 是我們對訊息進行操作的介面,可以通過session建立生產者、消費者、訊息等。Session 提供了事務的功能,如果需要使用session傳送/接收多個訊息時,可以將這些傳送/接收動作放到一個事務中。

我們可以在連線建立完成之後建立session:

Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);

這裡面提供了引數兩個引數,第一個引數是是否支援事務,第二個是事務的型別。

(4)JMS訊息生產者(Producer)

訊息生產者由Session建立,用於往目的地傳送訊息。生產者實現MessageProducer介面,我們可以為目的地、佇列或話題建立生產者。

MessageProducer producer = session.createProducer(dest);
MessageProducer producer = session.createProducer(queue);
MessageProducer producer = session.createProducer(topic);

建立完訊息生產者後,可以使用send方法傳送訊息:複製程式碼 程式碼如下:producer.send(message);

(5)JMS訊息消費者(Consumer)

訊息消費者由Session建立,用於接收被髮送到Destination的訊息。消費者實現MessageConsumer介面,我們可以為目的地、佇列或話題建立消費者。

MessageConsumer consumer = session.createConsumer(dest);MessageConsumer consumer = session.createConsumer(queue);MessageConsumer consumer = session.createConsumer(topic);

(6)JMS訊息監聽器

JMS訊息監聽器是訊息的預設事件處理者,他實現了MessageListener介面,該介面包含一個onMessage方法,在該方法中需要定義訊息達到後的具體動作。通過呼叫setMessageListener方法,我們給指定的消費者定義了訊息監聽器。

Listener myListener = new Listener();consumer.setMessageListener(myListener);

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。