首頁>技術>

1. 自動補償機制

在RabbitMQ裡,如果消費者在處理訊息時,業務邏輯出現異常,預設會執行補償機制(也就是訊息重試機制)。如果業務邏輯出現異常,是不會消費訊息的。基於上一篇部落格的例子《訊息中介軟體系列教程(13) -RabbitMQ-SpringBoot整合RabbitMQ》來演示一下。

現在消費者處理訊息的地方模擬一個異常:

生產者傳送訊息給消費者,會發現控制檯一直在列印錯誤日誌,也就是說,消費者一直在重試消費(補償):

也可以在RabbitMQ控制檯看到,訊息時沒有被消費的:

那麼RabbitMQ消費者的補償原理是怎樣的呢?

@RabbitListener 底層使用了AOP進行攔截,如果程式沒有拋異常,自動提交事務。如果AOP使用異常通知攔截獲取異常資訊的話,自動實現補償機制,該訊息會快取到RabbitMQ服務端進行快取,一直重試到不拋異常為準。

其實在application.yml配置檔案可以配置重試的次數與時間的,如重試5次,每次3秒:

執行程式後,發現重試了5次,3秒重試一次,而且RabbitMQ控制的訊息也消費了:

2. 如何合理選擇重試機制

下面有兩種情況:

情況1: 消費者獲取到訊息後,呼叫第三方介面,但介面暫時無法訪問,是否需要重試? (需要重試機制)情況2: 消費者獲取到訊息後,丟擲資料轉換異常,是否需要重試?(不需要重試機制)。

對於情況一是需要重試機制的,因為第三方API介面無法訪問可能是多種原因造成的,比如網路延時等。而情況二不需要重試機制,因為異常的程式碼是一直都會有異常的,只能透過下一次釋出版本解決。

那麼該如何解決呢?

可以採用“日誌記錄”+“定時任務健康檢查”+“人工補償”來解決。比如:出現了錯誤,可以日誌記錄下來,定時任務去定時查日誌,人工進行補償。

對於情況一,也許還會有疑問,如何實現手動重試呢?其實在模擬丟擲異常就可以了,如下虛擬碼:

@Component@RabbitListener(queues = "fanout_sms_queue")public class FanoutSmsConsumer { @RabbitHandler public void process(String msg) { System.out.println("簡訊消費者獲取生產者訊息msg:" + msg); Result result = OkHttpCientUtils(url,json); if(result == null){ throw new Exception("呼叫第三方介面失敗,準備執行重試機制"); } System.out.println("呼叫第三方介面與成功"); }}

本文連結:

https://blog.csdn.net/qq_20042935/article/details/103491483

6
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 高效大資料時間序列儲存的架構設計