RabbitMQ 消息的可靠投遞

mq 提供了兩種方式確認消息的可靠投遞java

  • confirmCallback 確認模式
  • returnCallback 未投遞到 queue 退回模式

 

在使用 RabbitMQ 的時候,做爲消息發送方但願杜絕任何消息丟失或者投遞失敗場景。RabbitMQ 爲咱們提供了兩個選項用來控制消息的投遞可靠性模式。git

rabbitmq 整個消息投遞的路徑爲:
producer->rabbitmq broker cluster->exchange->queue->consumergithub

message 從 producer 到 rabbitmq broker cluster 則會返回一個 confirmCallback 。
message 從 exchange->queue 投遞失敗則會返回一個 returnCallback 。咱們將利用這兩個 callback 控制消息的最終一致性和部分糾錯能力。segmentfault

 

對於消息異常,可使用如下方法進行解決緩存

  1. 使用RepublishMessageRecoverer這個MessageRecoverer會發送發送消息到指定隊列
  2. 給隊列綁定死信隊列,由於默認的RepublishMessageRecoverer會發送nack而且requeue爲false。這樣拋出一場是這種方式和上面的結果同樣都是轉發到了另一個隊列。詳見DeadLetterConsumer
  3. 註冊本身實現的MessageRecoverer
  4. 給MessageListenerContainer設置RecoveryCallback
  5. 對於方法手動捕獲異常,進行處理

 

rabbitTemplate的發送流程是這樣的:
1 發送數據並返回(不確認rabbitmq服務器已成功接收)
2 異步的接收從rabbitmq返回的ack確認信息
3 收到ack後調用confirmCallback函數
注意: 在confirmCallback中是沒有原message的,因此沒法在這個函數中調用重發,confirmCallback只有一個通知的做用。

 最安全的作法是是使用事務,可是這樣效率就會很低,每秒鐘處理的message在幾百條左右。對於高性能的 mq 來講是很是不可取的。安全

另外一種解決方法以下:在rabbitTemplate異步確認的基礎上
1 在本地緩存已發送的 message
2 經過 confirmCallback 或者被確認的 ack,將被確認的message從本地刪除
3 定時掃描本地的message,若是大於必定時間未被確認,則重發服務器

這種解決方式也有必定的問題
想象這種場景,rabbitmq接收到了消息,在發送ack確認時,網絡斷了,形成客戶端沒有收到ack,重發消息。(相比於丟失消息,重發消息要好解決的多,咱們能夠在consumer端作到冪等)。網絡

 

 

 

 

 

參考文獻:異步

https://segmentfault.com/a/1190000016041620函數

https://www.jianshu.com/p/6579e48d18ae

https://github.com/littlersmall/rabbitmq-access/blob/master/src/main/java/com/littlersmall/rabbitmqaccess/MQAccessBuilder.java

https://www.jianshu.com/p/6579e48d18ae

相關文章
相關標籤/搜索