相關知識
什麼是死信隊列
“死信”是RabbitMQ中的一種消息機制,當你在消費消息時,如果隊列裏的消息出現以下情況:
- 消息被否定確認,使用 channel.basicNack 或 channel.basicReject ,並且此時requeue 屬性被設置爲false。
- 消息在隊列的存活時間超過設置的TTL時間。
- 消息隊列的消息數量已經超過最大隊列長度。
那麼該消息將成爲“死信”,“死信”消息會被RabbitMQ進行特殊處理。如果配置了死信隊列信息,那麼該消息將會被丟進死信隊列中,如果沒有配置,則該消息將會被丟棄。
應用場景
當一個隊列中的消息必須要被正確消費,但是卻無法被正確消費,有很多情況可能導致出現這個問題,可能是消息本身的數據導致業務無法通過校驗,也可能是相關服務宕機導致,甚至可能只是網絡波動導致。此時該消息不能確認,也不能丟棄,更不能一直 requeue,那將變成一個死循環,這種消息不能一直呆在當前業務隊列阻塞其它消息,但又需要處理,把它們導航至死信隊列就是一種解決辦法,通過訂閱死信隊列可以對此類消息進行例外處理,例如通知相關人員檢查數據進行人工處理。
目標
整合 Spring boot 提供的 spring-boot-starter-amqp,實現消息消費失敗轉死信隊列
操作步驟
添加依賴
編碼(發送方)
配置
定義隊列
定義一個測試隊列 TestDeadQueue,併爲該隊列配置死信隊列,配置的方法就是在聲明隊列的時候,添加參數 x-dead-letter-exchange 及 x-dead-letter-routing-key,其實就是在消費失敗時,將消息使用該 exchange 及 routing 發送至指定隊列
測試發送
編碼(消費方)
配置
配置消費消息使用手動確認模式
定義隊列
消費
定義隊列 TestDirectQueue 的消費方法,在方法中調用了 basicReject 方法,用於告訴 RabbitMQ 消費失敗,調用 basicReject 方法時 requeue 參數必須爲 false,不然就會把消息重新加入當前隊列,由於隊列 TestDirectQueue 配置了死信隊列,於是 RabbitMQ 在接收到消費失敗的 ACK 後,將當前消息根據配置的 exchange 及 routing 進行再次發送,並從當前隊列中刪除,消息最終被髮送至隊列 DeadQueue。
源碼地址
本章源碼 : https://github.com/caiyuanzi-song/boot.git
結束語
死信隊列其實並沒有什麼神祕的地方,不過是綁定在死信交換機上的普通隊列,而死信交換機也只是一個普通的交換機,不過是用來專門處理死信的交換機。
總結一下死信消息的生命週期: