IT程式員開發必備-各類資源下載清單,史上最全IT資源,個人收藏總結。
Topic和queue的區別:
版本一:
JMS,Java Message Service,是JavaEE平台最重要的規範之一,也是企業開發中經常使用到的非同步技術。JMS規範目前支援兩種訊息模型:點對點(point to point,queue)和發布/訂閱(publish/subscribe,topic)。 點對點:
訊息生產者生產訊息發送到queue中,然後訊息消費者從queue中取出並且消費訊息。這裡要注意: 訊息被消費以後,queue中不再有儲存,所以訊息消費者不可能消費到已經被消費的訊息。 Queue支援存在多個消費者,但是對一個訊息而言,只會有一個消費者可以消費。 發布/訂閱
訊息生產者(發布)將訊息發布到topic中,同時有多個訊息消費者(訂閱)消費該訊息。和點對點方式不同,發布到topic的訊息會被所有訂閱者消費。 ==================================================================================================================
版本二:
在JMS中,Topic實現publish和subscribe語義。一條訊息被publish時,它將發到所有感興趣的訂閱者,所以零到多個 subscriber將接收到訊息的一個拷貝。但是在訊息代理接收到訊息時,只有啟用訂閱的subscriber能夠獲得訊息的一個拷貝。
JMS Queue執行load balancer語義。一條訊息僅能被一個consumer收到。如果在message發送的時候沒有可用的consumer,那麼它將被儲存一直到能處 理該message的consumer可用。如果一個consumer收到一條message後卻不響應它,那麼這條訊息將被轉到另一個consumer 那兒。一個Queue可以有很多consumer,並且在多個可用的consumer中負載平衡
Jms規範裡的兩種message傳輸方式Topic和Queue,兩者的對比如下表():
| |
Topic |
Queue |
| 概要 |
Publish Subscribe messaging 發布訂閱訊息 |
Point-to-Point 點對點 |
| 有無狀態 |
topic資料預設不落地,是無狀態的。 |
Queue資料預設會在mq伺服器上以檔案形式儲存,比如Active MQ一般儲存在$AMQ_HOME\data\kr-store\data下面。也可以配置成DB儲存。 |
| 完整性保障 |
並不保證publisher發布的每條資料,Subscriber都能接受到。 |
Queue保證每條資料都能被receiver接收。 |
| 訊息是否會丟失 |
一般來說publisher發布訊息到某一個topic時,只有正在監聽該topic地址的sub能夠接收到訊息;如果沒有sub在監聽,該topic就丟失了。 |
Sender發送訊息到目標Queue,receiver可以非同步接收這個Queue上的訊息。Queue上的訊息如果暫時沒有receiver來取,也不會丟失。 |
| 訊息發布接收策略 |
一對多的訊息發布接收策略,監聽同一個topic地址的多個sub都能收到publisher發送的訊息。Sub接收完通知mq伺服器 |
一對一的訊息發布接收策略,一個sender發送的訊息,只能有一個receiver接收。receiver接收完後,通知mq伺服器已接收,mq伺服器對queue裡的訊息採取刪除或其他動作。 |
以下是符合Jms1.1規範的使用Queue傳輸訊息的代碼,使用Active mq作為Jms的實現,想要更clean的代碼,可以考慮將Amq的實現DI:
Java代碼 public void testMySend() throws JMSException { Connection connection = new ActiveMQConnectionFactory( "admin" , "admin" , "tcp://localhost:61616" ).createConnection(); Session session = null ; Queue queue = null ; MessageProducer producer = null ; session = connection.createSession(false , Session.AUTO_ACKNOWLEDGE); queue=session.createQueue("myTest" ); producer= session.createProducer(queue); Message msg=session.createTextMessage("hello" ); producer.send(msg); producer.close(); session.close(); connection.close(); } public void testMyReceive() throws JMSException{ Connection connection = new ActiveMQConnectionFactory( "admin" , "admin" , "tcp://localhost:61616" ).createConnection(); Session session = connection.createSession(false , Session.AUTO_ACKNOWLEDGE); Queue queue = session.createQueue("myTest" ); MessageConsumer consumer= session.createConsumer(queue); consumer.setMessageListener(new MyListener()); connection.start(); consumer.close(); session.close(); connection.close(); }
消費端需要設定一個MessageListener:
Java代碼 private class MyListener implements MessageListener{ public void onMessage(Message message) { System.out.println("msg start!----------------" ); try { System.out.println("" +((TextMessage)message).getText()); } catch (JMSException e) { e.printStackTrace(); } System.out.println("msg end!----------------" ); } }
以下是符合Jms1.1規範的使用Topic 發送訊息的代碼:
Java代碼 public void testMyTopicPublisher() throws JMSException {