ActiveMQ消息的可靠性

我們在ActiveMQ消息持久化訂閱中,介紹了對Topic模式下的消息進行持久化訂閱,使其在暫無消費者消費或ActiveMQ服務重啓的情況下,不會導致消息的丟失,這裏其實就是保證了一定程度的消息可靠性。


那麼還會在其他地方發送消息不可靠的情況麼,首先我們從消息的生產及消費的流程中來看,消息有生產者發送到ActiveMQ消息隊列中,這個過程發送消息會發生消息一般在Queue模式下,是不會存在問題的,而在Topic模式下我們也是可以進行持久化訂閱的,見ActiveMQ消息持久化訂閱


因爲在生產者端,我們會使用send()方法向ActiveMQ發送消息,默認情況下,持久化消息以同步方式發送,send() 方法會被阻塞,直到 broker 發送一個確認消息給生產者,這個確認消息表示broker已經成功接收到消息,並且持久化消息已經把消息保存到存儲中。
在這裏插入圖片描述

這裏我們又會發現,上述我們一共發送了三次消息,每次只有在send()方法成功纔會確定提交到我們的ActiveMQ,但是如果在業務中,這三條消息是關聯的,這裏我們希望要不一起成功,要不一起失敗,那麼該如何處理呢。


這裏我們可以使用事務提交,事務中消息(無論是否持久化),會進行異步發送,send() 方法不會被阻塞。但是commit() 方法會被阻塞,直到收到確認消息,表示broker已經成功接收到消息,並且持久化消息已經把消息保存到存儲中。
在這裏插入圖片描述

這裏我們就會發現開啓了事務消息之後,我們在send()方法之後,消息不會立即到達ActiveMQ中,而必須等待commit之後,這裏我們可以通過ActiveMQ控制檯,進行debug驗證,其實這個事務消息和數據庫事務非常的類似。




看完了消息的生產者,那麼我們消息的消費者在消費消息時,會產生問題麼?如消息發送成功後,接收端接收到了消息。然後進行處理,但是可能由於某種原因,高併發也好,IO阻塞也好,這條消息在接收端處理失敗了。


但是如在Queue模式下的特性是一條消息,只會被一個接收端給接收,只要接收端A接收成功了,接收端B就不可能接收到這條消息,如果該消息是一些比較重要的消息,那麼就必須要保證消息的可靠性。在消費者端對對消息的確認有4種機制,如下:

  • AUTO_ACKNOWLEDGE = 1   自動確認
  • CLIENT_ACKNOWLEDGE = 2   客戶端手動確認
  • DUPS_OK_ACKNOWLEDGE = 3   自動批量確認
  • SESSION_TRANSACTED = 0   事務提交併確認

在這裏插入圖片描述


首先我們再看第一個 AUTO_ACKNOWLEDGE ,即自動確認應答,這裏我們需要特別注意的是,需要使用異步的方式來消費消息,因爲在同步接受消息時,在receive()方法接受到消息後(還未進行業務處理),這時消費者就會自動確認
在這裏插入圖片描述


而在異步接受消息的時候,即使用監聽器去消費消息,這裏會直到onMessage()方法執行完成後(包括了業務處理),纔會去自動確認
在這裏插入圖片描述

其中如果發生了異常,那麼ActiveMQ會對其進行重發,默認會重試6次,重發6次失敗後,就會進入死信隊列中,這裏我們在上述給其手動拋出一個異常,結果如下:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

注意:當我們使用messageListener方式消費消息時,可以在onMessage()方法中使用try-catch,這樣可以在處理消息出錯時記錄一些信息,而不是讓不斷去重發消息;如果你沒有使用try-catch,就有可能會因爲異常而導致消息重複接收的問題,這時就必須需要注意onMessage()方法中邏輯是否能夠兼容對重複消息的判斷。




第二個 CLIENT_ACKNOWLEDGE ,表示客戶端手動確認,這就意味着AcitveMQ將不會自動的爲我們進行ACK任何消息,需要我們自己擇機確認。
在這裏插入圖片描述
在這裏插入圖片描述

這裏我們需要就會使用同步消費方法了,因爲最終是由我們自己進行確認,但是如果忘記調用acknowledge()方法,將會導致當consumer重啓後,會接受到重複消息,因爲對於broker而言,那些尚未真正ACK的消息被視爲“未消費”。


我們可以在當前消息處理成功之後,可以立即調用message.acknowledge()方法來"逐個"確認消息,這樣可以儘可能的減少因網絡故障而導致消息重發的個數;當然也可以處理多條消息之後,間歇性的調用acknowledge()方法來一次確認多條消息,減少ack的次數來提升consumer的效率,不過需要自行權衡。




DUPS_OK_ACKNOWLEDGE 該參數類似於AUTO_ACK確認機制,可以自動批量確認,而且具有“延遲”確認的特點,ActiveMQ會根據內部算法,在收到一定數量的消息自動進行確認。

在此模式下,可能會出現重複消息,因爲當consumer故障重啓後,那些尚未ACK的消息(但是實際上已經消費了),就會重新發送過來。




最後一個 SESSION_TRANSACTED ,當session使用事務時,就是使用此模式。當決定事務中的消息可以確認時,必須調用session.commit() 方法,commit() 方法將會導致當前 session 的事務中所有消息立即被確認。
在這裏插入圖片描述

其實獲取session時,該方法的第一個參數表示是否支持事務,如果爲true,則會忽略第二個參數,自動被jms服務器設置爲SESSION_TRANSACTED


在事務開始之後的任何時機調用rollback() ,意味着當前事務的結束,事務中所有的消息都將被重發。當然在commit() 之前拋出異常,也會導致事務的rollback()


這裏其實和我們上述在消息生成者中,進行設置true使用了事務,其作用是相同的,就是我們需要使用commit() 來進行事務的提交。

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