標籤:des style blog java color 使用
1、發布/訂閱模型概覽
發布/訂閱(publish-and-subscribe)模型通常被簡寫為pub/sub模型。在這個模型中,訊息生產者成為發行者(publisher),而訊息消費者則稱為訂閱者(subscribe)。在點對點模型中,是將訊息發送到一個隊列中,而發布/訂閱模型則是將訊息發布給一個主題。發布/訂閱模型最重要的特性如下:
- 訊息通過一個稱為主題的虛擬通道進行交換。
- 每條訊息都會傳送給稱為訂閱者的多個訊息消費者。訂閱者有許多類型,包括持久性、非持久性和動態性。
- 發行者通常不會知道、也也意識不到哪一個訂閱者正在接收主題訊息。
- 訊息被推送給消費者,這意味著訊息會傳送給消費者,而無需請求。訊息通過一個稱為主題的虛擬通道進行交換。主題就是生產者發布訊息和訂閱者消費訊息的目的地。傳送給一個主題的訊息被自動推送給所有合格的消費者。
- 生產者和消費者之間沒有耦合。訂閱者和發行者可以在運行時動態添加,這使得系統的複雜性可以隨時間的推移而增長。
- 訂閱一個主題的每個用戶端都會接收到發布該主題的訊息副本。發行者生產的單條訊息可以複製並分發給成百上千的訂閱者。
使用發布訂閱模型時,JMS提供者會立即將發布到一個主題的訊息傳送給各個訂閱者。因此,與點對點模型不同,訂閱者並不是通過"掃描主題"來尋找屬於它們的訊息。相反,是由JMS提供者將訊息的一個副本傳送給各個訂閱者。
發布/訂閱模型和點對點的另一個主要區別是,發布/訂閱模型時在把訊息複製給每個訂閱者時,使用訊息選取器;而點對點模型則是在已將訊息添加到隊列之後,再使用訊息選取器。
訂閱者既可以是持久性的,也可以是非持久型的。非持久訂閱者只有在當前訂閱者是活動的,而且已經串連到主題的時候,才會接收到訊息;而持久訂閱者會接收發送到該主題的、它所需要的所有訊息,而不管該訂閱者活動與否。
訂閱者還可以是動態,或者是受管的。動態持久型訂閱者可以即時建立,而受管型訂閱者則是靜態,並且JMS提供者也知道這個受管訂閱者的存在。
何時使用發布/訂閱訊息傳送模型:如果要將事件或訊息廣播到多個訊息消費者,就會用到發布/訂閱模型。這裡最重要的一條就是,這條訊息可供多個消費者消費。發布/訂閱模
型的原理是將訊息的副本推送給多個訂閱者。
發布/訂閱訊息模型的使用: JMS初始化
在TLender類樣本中,suoyoudeJMS初始化邏輯都在建構函式中處理。TLender建構函式的代碼,除了兩處重要的區別外,幾乎和QBorrow建構函式完全相同。
首先,請注意TLender類的串連工廠、串連及會話對象,都和QBorrow類非常類似,除了它使用的是基於主題的介面而不是基於隊列的介面:
//串連到提供者、並獲得和JMS的串連Context ctx = new InitialContext();TopicConnectionFactory qFactory = (TopicConnectionFactory)ctx.lookup(topiccf);tConnection = qFactory.createTopicConnection();//建立JMS會話tSession = tConnect.createTopicSession(false,Session.AUTO_ACKNOWLEGE);//尋找請求和響應隊列topic = (Topic)ctx.lookup(topicName);//現在,建立已經完成,啟動串連tconnection.start();
這裡需要重點說明的是,儘管現在使用的是基於主題的API,但它的流程和點對點模型所用的基於隊列的API是相同的:
- 獲得JMS提供的一個初始上下文。
- 尋找串連工廠。
- 建立一個JMS串連。
- 建立一個JMS會話。
- 尋找目的地。
- 啟動串連。
發布訊息
一旦TLender類被初始化,利率就會通過命令列輸入進來。這事,系統從main方法中調用了publishRate方法,利率被發布到該主題智商。與點對點的例子不同,一旦訊息發布以後,TLender類將不再等待響應。這事根據發布/訂閱模型的去耦本質而為之;TLender類並不知道或並不關心誰在訂閱利率、它們怎樣處理資料,或者由多少訂閱者在接收利率資訊。也可能會出現這樣的情況:一些訂閱者正在接收利率資料,並由這個特定的貸方進行抵押利率波動的趨勢分析,而其他訂閱者(比如TBorrower類)則在進行分析利率,以決定是否再提供貸款。
在publishRate方法的一開始,我們建立了一個BytesMessage來儲存利率資料。可以選擇5中JMS訊息類型的任何一種,不過我們選擇了可移植性最強的BytesMessage:
BytesMessage msg = tSession.createBytesMessage();msg.writeDouble(newRate);
在建立訊息之後,我們接著又建立了TopicPublisher對象,它指定了希望發布訊息的主題,然後,我們使用了publish方法發布了訊息:
Topicpublisher publisher = tSession.createPublsher(topic);publisher.publish(msg);
像點對點模型的send方法一樣,在TopicSender對象中也有若干種重寫的publish方法可用。我們正在使用的這種方法,只接受JMSMessage對象作為唯一的參數。其他重寫的方法則允許您指定主題、傳送模型、訊息優先順序,還有訊息有效期間。由於我們並未制定任何其他值,所有訊息優先順序被設定為普通(4),傳送模型被設定為持久性訊息(DeliveryMode.PERSISTENT),而有效期間則被設定為0,表示訊息將永不到期。所有這些參數都可以使用其他publish方法來重寫。
這裡有一點要說明:雖然請求/應答肯定能夠適用於發布/訂閱模型,但是它在當今基於主題的訊息傳送模型中並不常見,這主要是因為發布/訂閱模型的本質特性:發布/訂閱模型通常用於廣播事件或資訊,它並不期望對該廣播作出響應。
持久訂閱者和非持久訂閱者
如果您要運行TBorrower類,並隨後發布若干種利率,TBorrower類就會得到新利率,並判斷這個利率是否合適。不過,如果您要終止TBorrower類,發布一些新利率,隨後再重啟TBorrower類,您就不會獲得在TBorrower類未運行期間發布到該主題的利率。這事為什嗎?原因就在於您所建立的TBorrower類是一個非持久訂閱者:
TopicSubscriber subscribe = tSession.createSubscriber(topic);
只有非持久訂閱者在主動偵聽一個主題時,才會接收到訊息。否則,它們將會錯過這些訊息。在發布/訂閱模型中,並不存在儲存所有訊息的"主題"這樣一個真實的概念;確切的說,當JMS提供者接收到一條訊息時,提供者將為每個訂閱者製作該訊息的一個副本。如果訂閱者不是活動的,它就不會接收該訊息的副本。這個概念5-3所示。
另一方面,持久訂閱者會接收發送到該主題的所有訊息(依靠該訂閱者使用的訊息選取器),無論該訂閱者活動與否。這通常稱為"儲存並轉寄(store-and-forward)"訊息傳送。持久訂閱者”儲存並轉寄"的概念如下: