關於 RabbitMQ 的 Dead-Letters-Queue 「死信隊列」

 
來自一個隊列的消息能夠被當作‘死信’,即被從新發布到另一個「exchange」去,這樣的狀況有:
  • 消息被拒絕 (basic.reject or basic.nack) 且帶 requeue=false 參數
  • 消息的TTL-存活時間已通過期
  • 隊列長度限制被超越(隊列滿)
 
Dead letter exchanges (DLXs) are normal exchanges.
 
For any given queue, a DLX can be defined by clients using the queue's arguments, or in the server using policies.
 
Dead Letter Pattern
     「死信」模式指的是,當消費者不能處理接收到的消息時,將這個消息從新發布到另一個隊列中,等待重試或者人工干預。
這個過程當中的exchange和queue就是所謂的"Dead Letter Exchange 和 Queue"。
     關鍵是如何區分「消費失敗」和「處理失敗」?消費失敗須要送到死信隊列,而處理失敗不須要。大部分狀況都屬於「處理失敗」。
 
Dead-Letter-Exchange, routing-key, queue 均可以從 rabbitmq 的管理後臺配置。
 
若是用 Spring-rabbitmq 來使用 Dead-Letter-Exchange 和 Queue 須要對。
     從 3.9 Exception Handling 能夠知道,設置 defaultRequeueRejected = false 會丟棄消息或者從新發布到死信隊列中。
     若是是 Convert 出現異常,那麼會直接 "reject-dont-requeue".
 
< rabbit:listener-container defaultRequeueRejected="false"   connection-factory = "connectionFactory" >
   < rabbit:listener ref = "listener" method = "listen" queue-names = "async_request_queue" />
</rabbit: listener-container>
 
     也能夠在 handler 中拋出 "AmqpRejectAndDontRequeueException" 來告訴spring容器,不要從新requeue這條消息。
 
     而後配置 Dead Letter Exchange 並綁定 Dead Letter Queue.
 
<rabbit:queue name="q.with.dlx">
    <rabbit:queue-arguments> 
        <entry key="x-dead-letter-exchange" value="dlx"/>
        <entry key="x-message-ttl" value="10000" value-type="java.lang.Long"/>
    </rabbit:queue-arguments>
</rabbit:queue>

<rabbit:queue name="dlq"/>

<rabbit:direct-exchange name="dlx">
    <rabbit:bindings>
        <rabbit:binding key="q.with.dlx" queue="dlq"/>
    </rabbit:bindings>
</rabbit:direct-exchange>
     若是 exchange 或者 queue 是 鏡像/持久的,那麼須要先刪除再啓動 spring-amqp 程序,這樣 xml 中的 exchange 和 queue 配置才能生效,
不然服務器端配置不會修改,啓動生成者時拋異常,啓動失敗。
     對於部署,能夠考慮使用新隊列來避免須要先刪除已有隊列的問題。
 
常見問題:
     緣由:queue已經存在,可是啓動 consumer 時試圖設定一個 x-dead-letter-exchange 參數,這和服務器上的定義不同,server 不容許因此報錯。若是刪除 queue 從新 declare 則不會有問題。或者經過 policy 來設置這個參數也能夠不用刪除隊列。
     參考 blog
 
參考:
相關文章
相關標籤/搜索