RabbitMQ提供了一種QOS(Quality of Service ,服務質量保證)功能,即在非自動確認消息的前提下,如果一定數目的消息(通過基於consume或者channel設置QOS的值)未被確認前,不進行消費新的消息。
在RabbitMQ消息的獲取方式中,無論是推送Consume、拉取Get哪一種方式,只要不進行消息確認,那麼RabbitMQ會認爲該消息未被成功處理,則不會將其移除,一般情況下我們讓消費者處理一批指定數量的消息,然後再進行批量確認,其用法在RabbitMQ消息應答的最後手動批量確認中,已有相關介紹。
這裏假設我們忘記了進行批量確認,或者批量確認出現了問題,那麼消費者一直在消費消息且不給予消息確認,那麼服務最後就會出現問題,這裏就可以利用RabbitMQ的QOS預取模式,來對消費者進行流控,從而限制未ack的消息數量。
注意: 消費確認模式必須是非自動確認ACK機制(這個是使用RabbitMQ的QOS預取模式的前提條件,否則會QOS不生效)
其使用的其實比較的簡單,首先需要設置QOS的值;另外,還可以基於消費者Consume和信道Channel的粒度進行設置(global),如下:
其中basicOos()
有多個參數,其參數含義如下:
-
prefetchSize: 最多傳輸的內容的大小的限制,0爲不限制,但據說prefetchSize參數,RabbitMQ暫未對其沒有實現。
-
prefetchCount: 會告訴RabbitMQ不要同時給一個消費者推送多於N個消息,即一旦有N個消息還沒有ack,則該消費者Consumer將阻塞block掉,直到有消息進行ack確認
-
global: true/false,表示是否將上面設置應用於channel,簡單點說,就是上面限制是信道channel級別的還是消費者consumer級別。
下面我們調整下參數進行測試,如我們在消費者的生產者發送3條消息,如下:
然後再消息的消費者端,我們進行消息的消費,這裏採用手動確認ack的機制,但是我們不進行確認,進行測試
上述這三條消息被消費者消費了,但是並未確認,所以我們關閉該消費者,再次啓動該隊列的消費者還是可以收到三條消息的。
這裏我們然後再使用RabbitMQ的QOS預取模式,對其進行流控,從而限制未ack的消息數量。如我們限制一個信道最多隻能有2個未確認的消息,如下:
另外對於basicOos()
的參數global
,上述進行了介紹,true表示限制信道,false表示限制單獨的消費者,但是如果我們同時進行設置的話,如下:
RabbitMQ將此解釋爲意味着兩個預取限制應該彼此獨立地強制執行,即兩個條件都需要進行滿足
之前我們在RabbitMQ的基礎使用 —— Direct模式(二)中介紹了一個連接可以有多個信道,其實我們一個信道中肯定也是可以有多個消費者的,我們只需要在其中聲明多個消費者即可:
這樣的話,一個信道中就存在兩個消費者了,其也是輪詢進行消費消息的,那麼上述的設置的效果爲:每個消費者最多可以有50個未確認的消費,但是該信道所有的消費者加起來最多隻能有100個未確認的消息。