五.RabbitMQ生產者/消費者消息確認

01 爲什麼要消息確認

在一些場合,如轉賬、付費時每一條消息都必須保證成功的被處理。AMQP是金融級的消息隊列協議,有很高的可靠性,這裏介紹在使用RabbitMQ時怎麼保證消息被成功處理的。

消息確認可以分爲兩種:一種是生產者發送消息到Broke時,Broker給生產者發送確認回執,用於告訴生產者消息已被成功發送到Broker;

一種是消費者接收到Broker發送的消息時,消費者給Broker發送確認回執,用於通知消息已成功被消費者接收。下邊分別介紹生產者端和消費者端的消息確認方法

02 生產者端消息確認

生產者端的消息確認:當生產者將消息發送給Broker,Broker接收到消息給生產者發送確認回執。生產者端的消息確認有兩種方式:tx機制和Confirm模式。

1. Tx機制模式

tx機制可以叫事務機制,RabbitMQ中有三個與tx機制的方法:txSelect,txcommit和txRollback。channe.txSelect用於將當前channel設置成一個transaction模式,channe.txCommit提交事務,channel.txRollback回滾事務。

使用tx機制,我們首先要通過txSelect方法開啓事務,然後發佈消息給broker服務器,如果txCommit提交成功了,則說明消息成功被broker接受了;

如果txCommit執行之前broker異常崩潰或者由於其他原因拋出異常,這個時候我們可以捕獲異常,通過txRollback回滾事務。

準備工作:如圖

看一個tx機制的簡單實現:

 執行結果如下:

2. Confirm模式

C#的RabbitMQ API中,有三個與Confirm相關的方法:ConfirmSelect,WaitForCnofirms和WaitForCnofirmOrDie。channel.ConfirmSelect表示開啓Confirm模式。channel.WaitForConfirms等待所有消息確認,如果所有的消息都被服務端成功接收返回true,只要有一條沒有被成功接收就返回false。

channel.WaitForConfirmsOrDie和WaitForConfirms作用類型,也是等待所有消息確認,區別在於該方法沒有返回值(Void),如果有任意一條消息沒有被成功接收,該方法會立即拋出一個OperationInterrupedException類型異常.

下面看一個簡單的案例:

執行結果如下:

 

03 消費者端消息確認

生產者端的消息確認:從Broke發送到消費者時,RabbitMQ提供了兩種消息確認的方式:自動確認和顯示確認。

1、自動確認:

當RabbbitMQ將消息發送給消費者後,消費者端接收到消息後,不等待消息處理結束,立即自動回送一個確認回執。自動確認的用法十分簡單,設置消費方法的參數autoAck爲true即可;如下內容:channel.BasicConsume(queue:"myqueue",autoAck: true, consumer: consumer);

 

注意:Broker會在接收到確認回執時刪除消息,如果消費者接收到消息並返回了確認回執,然後這個消費者在處理消息時掛了,那麼這條消息就再也找不回來了。

 2、顯示確認

我們知道自動確認可能會出現消息丟失的問題,我們不免會想到:Broker收到回執後才刪除消息,如果可以讓消費者在接收消息時不立即返回確認回執,等到消息處理完成後(或者完成一部分的邏輯)再返回確認回執,這樣就保證消費端不會丟失消息了!這正是顯式確認的思路。使用顯示確認也比較簡單,首先將Resume方法的參數autoAck設置爲false在消費端使用代碼 channel.BasicAck/BasicReject等方法 來確認和拒絕消息。

 

生產者代碼:

 

消費者代碼如下:

介紹一下代碼中標紅的兩個方法:

channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false); 方法用於確認消息,deliveryTag參數是分發的標記,multiple表示是否確認多條。

 

channel.BasicReject(deliveryTag: ea.DeliveryTag, requeue: false); 方法用於拒絕消息,deliveryTag也是指分發的標記,requeue表示消息被拒絕後是否重新放回queue中,true表示放回queue中,false表示直接丟棄

 

嘗試運行:如下圖

 

一些意外的情況:使用顯式確認時,如果消費者處理完消息不發送確認回執,那麼消息不會被刪除,消息的狀態一直是Unacked,這條消息也不會再發送給其他消費者。如果一個消費者在處理消息時尚未發送確認回執的情況下掛掉了,那麼消息會被重新放入隊列(狀態從Unacked變成Ready),有其他消費者存時,消息會發送給其他消費者。

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