RabbitMQ死信隊列管理

概述

之前我們折騰了RabbitMQ的搭建,RabbitMQ的集羣。所以,很快我就在公司封裝好並推廣了消息隊列的使用。我們因爲僅使用發佈訂閱和點對點的模型,所以很簡單而單純,就用起來了,但是,我們很快發現了一個問題。因爲剛開始,我沒有配置日誌,啓動的時候直接用nohup啓動的,日誌直接看默認的文本。然後,我們的消費服務是有問題的,而我爲了消息不丟失,設置了消息總是會重新投入到隊列裏,然後,因爲一些bug,消息一直處理失敗,於是很快日誌就塞滿了磁盤。雖然後來我配了日誌的大小磁盤不會滿了,但是,這個問題還是會很影響使用的。爲了解決這個問題,我們提出了死信隊列。

死信隊列是什麼

其實,在rabbitMQ中,叫死信交換器。我們需要一個隊列訂閱這個交換器來消費過來的消息,這個隊列,叫做死信隊列。

怎麼用死信隊列

其實,死信交換器就是一個普通的交換器,它具備交換器的一切特徵,沒任何特殊的地方。我們需要在定義隊列的時候指定隊列的死信交換器,如下:

Map<String, Object> args = new HashMap<String, Object>();
args.put("x-dead-letter-exchange", "some.exchange.name");
channel.queueDeclare("myqueue", false, false, false, args);

那麼,在消息死亡的時候,就會自動路由到這個交換器了。那麼,消息什麼時候會死亡呢?以下三種情況:

  • 消息被拒絕(basic.reject/ basic.nack)並且requeue=false
  • 消息TTL過期
  • 隊列達到最大長度
      其中,最後一種情況我沒有測試。第一種情況和第二種情況我測試了。是沒有問題的。其實,到此,死信隊列就搞定了,但是,我還趟了一個大坑,下面介紹。

交換器路由

什麼坑呢?我開始的時候把交換器的類型設置成了direct,routingKey設置成了空字符串,然後,死活收不到消息。後來,我把direct改成了fanout,就收到了。至此,我確定了交換器就是普通的交換器,我的死信隊列也是對的。
  交換器路由規則如下:

  • direct:只會路由到routingKey相同的隊列中,如果有兩個相同的,則複製分發。
  • fanout:無視routingKey,分發到所有的訂閱者中,這也是爲什麼改了之後就收到消息了。
  • topic:根據表達式來路由routingKey,*表示任意一個字母,#表示任意多個字母。
  • header:這個我們就不介紹了,根據官方說法,這個性能很低,而且可以用其它的來實現,所以總是不應該使用。

demo

請參考https://gitee.com/naturetrible/ntbrick.demo 中的rabbitmq-dlx項目

參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章