小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

ActiveMQ分享(一)JMS簡介

 gyb98 2011-04-09
一、概述 

  Message,即消息。人與人之間通過消息傳遞信息。言語、眼神、肢體動作都可被視為消息體。當然還有我們經(jīng)常用到的郵件、短信。計算機系統(tǒng)也由消息來主導(dǎo)運行。每一條指令的執(zhí)行,每一個數(shù)據(jù)包的傳遞。軟件系統(tǒng)間的合作也不例外,消息告訴各個系統(tǒng)應(yīng)該怎樣協(xié)作。事件處理機制,也是消息傳送的過程。消息無處不在。 

  消息分為同步消息和異步消息。同步消息在接收到對方的返回前,需要掛起,直到返回或超時。異步消息只需要發(fā)送消息,不需要對方系統(tǒng)的立即反饋。 

  同步消息如java RPC調(diào)用,同步調(diào)用依賴于被調(diào)用方,如果被調(diào)用方失敗或網(wǎng)絡(luò)錯誤,那么程序就沒辦法繼續(xù)執(zhí)行下去,造成一個系統(tǒng)最薄弱的環(huán)節(jié)依賴于對方系統(tǒng)。而多個系統(tǒng)通過同步調(diào)用方式耦合在一起的時候,那么可靠性取決于最薄弱的一方系統(tǒng)。而異步調(diào)用能增強一個系統(tǒng)的健壯性。當然,不是任何情況都適合異步調(diào)用,還是那句話,能異步的地方,盡量異步。 

  異步消息,如同一個郵箱系統(tǒng),我們把信件丟入郵桶,郵遞員會更具上面的地址,送達到這封信要去的地方。郵箱和信件格式由郵局提供定義,比如郵箱需要有一個口子投遞郵件,郵件需要有地址,郵政編碼等等。而這些郵箱具體的加工和制作均交由各自的廠商來完成。 
在java消息領(lǐng)域,我們也有一個稱為消息中間件的東西,來提供這樣一個服務(wù)。消息的發(fā)送、消費接口、消息體的格式等都由JMS來定義,而具體的實現(xiàn)由各個消息中間件廠商來實現(xiàn)。JMS是sun公司對于消息中間件的一個規(guī)范。對java領(lǐng)域里的消息起到舉足輕重的作用。以前的消息交互,均各自實現(xiàn)一套格式,如同一個國家的人都用不同的方言跟另外來自不同省份的人交流一樣。自從規(guī)范了普通話,我們的交流成本降低了。這也正如JMS規(guī)范在整個java消息領(lǐng)域的作用。 

二、JMS簡介 

  JMS1.1規(guī)范定義了一些概念和一組API,可以使得在我們利用消息系統(tǒng)的過程中,不依賴于各個廠商的具體實現(xiàn),便能寫出消息代碼。由于不依賴具體廠商實現(xiàn),這樣的代碼有很好的移植性。 
JMS1.1定義了的部分概念: 
1、JMS客戶端:接收或發(fā)送消息的java系統(tǒng) 
2、JMS消息體:系統(tǒng)間發(fā)送的消息體 
3、JMS提供商:JMS規(guī)范實現(xiàn)廠商 
4、JMS管理對象:預(yù)先配置好的用于JMS客戶端的JMS對象。如ConnectionFactory跟JMS服務(wù)端的連接工廠,Destination 接收和發(fā)送消息的目標地址等 
5、JMS Domain:JMS定義了兩種域模型,一種是PTP(point-to-point)即點對點消息傳輸模型,一種是pub/sub(publish-subscribe)即發(fā)布訂閱模型。 
  PTP通過一個先進先出的queue實現(xiàn)。很多人在這個PTP概念上有所誤解,所謂點對點不是指生產(chǎn)者和消費者只有一個。PTP如下圖所示: 

 

  我們可以看到,一個或多個生產(chǎn)者發(fā)送消息,消息m2先抵達了queue,然后m1也發(fā)出了,并一同存在于一個先進先出的queue里面。消費者也存在一個或多個,對queue里的消息進行消費。但消息被隨機的一個消費者消費且僅消費一次。 

在pub/sub消息模型中,消息被廣播給所有訂閱者。如下圖: 


 

JMS1.1定義了如下接口: 


JMS通用接口JMS PTP接口JMS pub/sub 接口描述
ConnectionFactoryQueueConnectionFactoryTopicConnectionFactory創(chuàng)建與JMS服務(wù)的連接
ConnectionQueueConnectionTopicConnectionJMS服務(wù)的連接,可創(chuàng)建Session
DestinationQueueTopic發(fā)送接收消息的目標,Queue和Topic均可視為一種Destination
SessionQueueSessionTopicSessionSession
MessageProducerQueueSenderTopicPublisher消息發(fā)送者
MessageConsumerQueueReceiver、QueueBrowserTopicSubscriber消息接收者/瀏覽者/訂閱者



接口關(guān)系如下: 


 


  可以看到一個JMS應(yīng)用的發(fā)送端的標準流程是:創(chuàng)建連接工廠>創(chuàng)建連接>創(chuàng)建session>創(chuàng)建發(fā)送者>創(chuàng)建消息體>發(fā)送消息到Destination(queue或topic)。 

  接收端則為:創(chuàng)建連接工廠>創(chuàng)建連接>創(chuàng)建session>創(chuàng)建接收者>創(chuàng)建消息監(jiān)聽器監(jiān)聽某Destination的消息>獲取消息并執(zhí)行業(yè)務(wù)邏輯 

下面展示了JMS的編碼模板: 

發(fā)送端: 

   
Java代碼  收藏代碼
  1. public class QueueSender {  
  2.         public static void main(String[] args) throws JMSException{  
  3.             ConnectionFactory factory=new ActiveMQConnectionFactory("tcp://localhost:61616");//這里為簡便,依賴ActiveMQ的JMS實現(xiàn)?,F(xiàn)實程序中可以通過jndi查找方式查找factory,這樣徹底避免關(guān)聯(lián)特定JMS實現(xiàn)者。并擁有最大的可移植性。  
  4.             Connection connection=factory.createConnection();  
  5.             Session session=connection.createSession(false,Session.AUTO_ACKNOWLEDGE);  
  6.             Message message=session.createTextMessage("Hello World!"+new Date().getTime());  
  7.             Queue queue=new ActiveMQQueue("queue.somebody");//同上,這里依賴了ActiveMQ的JMS實現(xiàn),現(xiàn)實中可以采用jndi查找方式獲得Queue。  
  8.             MessageProducer producer=session.createProducer(queue);  
  9.             producer.send(message);  
  10.             session.close();  
  11.             connection.close();  
  12.         }  
  13.     }  


接收端: 
       
Java代碼  收藏代碼
  1. public class QueueReceiver {  
  2.             public static void main(String[] args) throws JMSException{  
  3.                 ConnectionFactory factory=new ActiveMQConnectionFactory("tcp://localhost:61616");  
  4.                 Connection connection=factory.createConnection();  
  5.                 Session session=connection.createSession(false,Session.AUTO_ACKNOWLEDGE);  
  6.                 Queue queue=new ActiveMQQueue("queue.somebody");  
  7.                 MessageConsumer receiver=session.createConsumer(queue);//創(chuàng)建兩個接收者,同時消費同一個queue的消息。queue里的消息派發(fā)且僅派發(fā)一次給唯一一個消費者。  
  8.                 MessageConsumer receiver2=session.createConsumer(queue);  
  9.                 receiver.setMessageListener(new QueueMessageListener("1"));  
  10.                 receiver2.setMessageListener(new QueueMessageListener("2"));  
  11.                 connection.start();  
  12.             }  
  13.         }  


消息偵聽者: 
   
Java代碼  收藏代碼
  1. public class QueueMessageListener implements MessageListener{  
  2.     private String num;  
  3.     public QueueMessageListener(String num){  
  4.         super();  
  5.         this.num=num;  
  6.     }  
  7.     public QueueMessageListener(){  
  8.         super();  
  9.     }  
  10.     public void onMessage(Message message) {  
  11.         System.out.println(message.toString()+num);  
  12.     }  


  我們安裝了ApacheMQ之后,啟動本地MQ服務(wù),便能測試這幾個類的執(zhí)行方式,觀察執(zhí)行過程。我們可以發(fā)現(xiàn)消息僅被消費了一次,JMS提供商必須保證一條消息不會重復(fù)被消費,當然更不能丟失。 

  在PTP下,我們建立一個queue以后,如果沒有消費者連入該queue,那么消息生產(chǎn)者發(fā)送的消息將堵塞在queue里面,直到有消費者來消費。如果消費者出現(xiàn)故障,不再連入queue,消息還會保存在queue里面,等待下次消費者的連入,再進行消費。在pub/sub模型下,如果消費者出現(xiàn)故障,那么所有的消息,將不在為之保留,下次連接之時,只能消費此時生產(chǎn)者發(fā)送的消息。JMS于是定義了另一種訂閱者,叫Durable Subscription(持久訂閱者),該訂閱者在第一次連上topic后,就注冊了該topic的消息,消息會在消費者不可用的情況下為之保留消息,并在其再次連上topic后,重推消息給消費者。 

  理解了JMS中的兩種消息模型以后,我們來說說JMS中的消息體格式。JMS對消息體定為三個部分 1)head 消息頭信息 2)properties 消息屬性值 3)body 消息內(nèi)容。如下圖所示: 

 

其含義大致解釋如下: 

頭類型描述設(shè)置方
JMSDestination描述該消息發(fā)往的目的地在發(fā)送方法中設(shè)定
JMSDeliveryModeNON_PERSISTENT 非持久化 表示消息發(fā)往JMS消息服務(wù)器之后,保存在內(nèi)存中,不做持久化;PERSISTENT 持久化 消息發(fā)往JMS消息服務(wù)器之后,持久化數(shù)據(jù)。以保證消息服務(wù)器拓機造成的消息丟失發(fā)送方法中設(shè)定
JMSExpiration消息過期時間。消費者在發(fā)送消息時,可設(shè)定消息的time-to-live時間,如producer.setTimeToLive(10000),在消息發(fā)送后,該時間保留在消息的JMSExpiration字段中,如果在指定的這段時間內(nèi)消息未被消費,該消息將會被丟棄。在發(fā)送方法中設(shè)定
JMSPriority消息優(yōu)先級,JMS把消息分為10個等級,0-4為普通優(yōu)先級,5-9為加快優(yōu)先級,ActiveMQ中默認的消息優(yōu)先級為4在發(fā)送方法中設(shè)定
JMSMessageId消息唯一性ID,必須以“ID:”為前綴在發(fā)送方法中設(shè)定
JMSTimestamp消息發(fā)送時間,表示消息的發(fā)送時間點,而非傳送時間在發(fā)送方法中設(shè)定
JMSCorrelationID客戶端
JMSReplyTo客戶端
JMSType客戶端
JMSRedeliveredJMS提供商
屬性值含義
properties
消息體含義
body消息體分為1:StreamMessage2:MapMessage 3:TextMessage 4:ObjectMessage 5:BytesMessage


再談消息可靠性 

    在上面,談及消息體格式定義中,有個字段 JMSDeliveryMode用來表示該消息發(fā)送后,JMS提供商應(yīng)該怎么處理消息。PERSISTENT(持久化)的消息在JMS服務(wù)器中持久化。接收端如果采用點對點的queue方式或者Durable Subscription(持久訂閱者)方式,那么消息可保證只且只有一次被成功接收。NON_PERSISTENT(非持久化)的消息在JMS服務(wù)器關(guān)閉或宕機時,消息丟失。根據(jù)發(fā)送端和接收端采用的方式,列出如下可靠性表格,以作參考。 

引用
注意:以下的可靠性不包括JMS服務(wù)器由于資源關(guān)系,造成的消息不能持久化等因素引起的不可靠(該類不可靠應(yīng)該是JMS提供商或硬件引起的的資源和處理能力的極限問題,應(yīng)該由管理人員解決)。也不包括消息由于超時時間造成的銷毀丟失。

消息發(fā)送端消息接收端可靠性及因素
PERSISTENTqueue receiver/durable subscriber消費一次且僅消費一次??煽啃宰詈?,但是占用服務(wù)器資源比較多。
PERSISTENTnon-durable subscriber最多消費一次。這是由于non-durable subscriber決定的,如果消費端宕機或其他問題導(dǎo)致與JMS服務(wù)器斷開連接,等下次再聯(lián)上JMS服務(wù)器時的一系列消息,不為之保留。
NON_PERSISTENTqueue receiver/durable subscriber最多消費一次。這是由于服務(wù)器的宕機會造成消息丟失
NON_PERSISTENTnon-durable subscriber最多消費一次。這是由于服務(wù)器的宕機造成消息丟失,也可能是由于non-durable subscriber的性質(zhì)所決定


消息的通知確認 
在客戶端接收了消息之后,JMS服務(wù)怎樣有效確認消息是否已經(jīng)被客戶端接收呢?Session session=connection.createSession(false,Session.AUTO_ACKNOWLEDGE);這段代碼創(chuàng)建一個非事務(wù)性的session,并采用auto_acknowledge方式通知JMS服務(wù)器。如果采用事務(wù)性session時,通知會伴隨session的commit/rollback同時發(fā)送通知。在我們采用非事務(wù)session時,有三種通知方式。 
通知方式效果
DUPS_OK_ACKNOWLEDGEsession延遲通知。如果JMS服務(wù)器宕機,會造成重復(fù)消息的情況。程序必須保證處理重復(fù)消息而不引起程序邏輯的混亂。
AUTO_ACKNOWLEDGE當receive或MessageListener方法成功返回后自動通知。
CLIENT_ACKNOWLEDGE客戶端調(diào)用消息的acknowledge方法通知




JMS就先簡要的介紹到這里,詳細資料請參看JMS1.1規(guī)范。關(guān)于ActiveMQ的文章文章請繼續(xù)關(guān)注 ActiveMQ分享(二) 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多