2014-04-03 79 views
7
  1. DefaultConsumer
    我DemoConsumer從DefaultConsumer繼承。
    我注意到,以這種方式工作handleDelivery()是從ThreadPool調用的。 (我打印Thread.currentThread()。getName()我每次看到pool-1-thread-1/2/3/4。
    我也測試了幾次,看到訂單被保存。
    Just確保 - 因爲不同的線程調用句柄傳遞 - 它會亂了我的訂單RabbitMQ的Java客戶端使用DefaultConsumer VS QueueingConsumer

  2. QueueingConsumer
    所有的Java教程的使用QueueingConsumer使用消息
    在它被提到的一個過時的類的API文檔。
    我應該將我的代碼更改爲從DefaultConsumer繼承嗎?是否該教程過時?

謝謝。

+0

你的意思是「它會攪亂我的訂單嗎?」 ? 主題順序或消息順序? – Gabriele

回答

12

是的,DefaultConsumer使用一個可以更改的內部線程池。 使用ExecutorService爲:

ExecutorService es = Executors.newFixedThreadPool(20); 
Connection conn = factory.newConnection(es); 

閱讀http://www.rabbitmq.com/api-guide.html「高級連接選項」。

你可以從「QueueingConsumer」 doc閱讀:

因此,它現在可以安全地直接實現消費者或延長DefaultConsumer。

我從來沒有使用過QueueingConsumer,因爲它沒有正確的事件驅動。

正如你可以在這裏看到:

QueueingConsumer consumer = new QueueingConsumer(channel); 
channel.basicConsume(QUEUE_NAME, true, consumer); 
while (true) { 
    QueueingConsumer.Delivery delivery = consumer.nextDelivery(); 
    /// here you are blocked, waiting the next message. 
    String message = new String(delivery.getBody()); 
} 

在這種情況下,一個典型的問題是如何關閉訂閱,一個共同的解決辦法是在本地主機發送一個標記接近的消息。其實我不喜歡這麼多。

如果擴展DefaultConsumer相反,你可以正確地關閉申購和通道:

public class MyConsumer extends DefaultConsumer {...} 

然後

public static void main(String[] args) { 
MyConsumer consumer = new MyConsumer (channel); 
String consumerTag = channel.basicConsume(Constants.queue, false, consumer); 
System.out.println("press any key to terminate"); 
System.in.read(); 
channel.basicCancel(consumerTag); 
channel.close(); 
.... 

總之,你不應該擔心的消息順序,因爲如果所有的消息順序是正確的,但我認爲你不能假設它,因爲如果有問題,你可能會失去消息順序。如果您絕對需要維護消息順序,則應該包含順序標籤以在消費方重新構建消息順序。

而且你應該擴展DefaultConsumer。

+0

非常感謝你 –

+0

嗨,當擴展DefaultConsumer時如何做rateLimiter,因爲當擴展DefaultConsumer時我無法控制是否接收消息,但是當使用QueueingConsumer時,我可以在consumer.nextDelivery()之前拒絕消費。 – chou