消息“丟失”的可能原因及解決辦法
消息“丟失”是指消息已經從客戶端成功發送到了服務端,且服務端返回了成功的響應。但是在消費時,該消息未被推送給客戶端且已經從服務端刪除,未來無法消費該消息。
可能原因
一般情況下,云消息隊列 RabbitMQ 版并不會出現消息丟失,只要遵循使用限制,在最大消息保留時間內對消息進行消費,且在最大重試次數前作出有效應答,即可確保消息不丟失。使用限制,請參見使用限制。
客戶端未收到消息,通常是如下幾種原因:
生產者問題
消息未發送成功,這種情況下,消息一般未到達服務端,或者并未被發送到指定Queue,從而導致這條消息未被記錄、存儲。自然也就無法消費到。
消費者問題
消費者運行異常,導致消息無法消費到。
消費者代碼問題,導致未收到隊列的消息推送。
隊列中存在消息堆積,導致消息無法消費到。
QoS等參數設置不合理,導致消息超過重推次數上限進入死信。
解決辦法
您可以參考如下流程進行自助診斷。
生產者問題
確認消息成功發送進入RabbitMQ實例
可以為每條消息設置單獨的Message ID,在消息發送時攜帶Message ID發往云消息隊列 RabbitMQ 版服務端,此時這條消息便可依據這唯一Message ID進行跟蹤。
針對某些未消費消息,可以根據Message ID在如下幾個位置進行查詢。
若根據上述幾個方法查到消息確實已經被云消息隊列 RabbitMQ 版服務端存儲,則可以重點排查后續的消息推送過程是否存在異常。
若是沒有查詢到消息,則需要檢查生產者代碼的參數是否正確,隊列是否正確綁定。
消費者問題
消息的推送事件可以在消息軌跡內看到。若消息有推送事件,需要查看所在隊列是否存在堆積,導致消息推送阻塞。若無堆積情況,或消息有推送事件,但是客戶端一直未消費到,則需要針對消費者的運行情況進行排查。
確認消費者運行正常
檢查消費者運行情況,例如CPU、內存等資源是否充足,是否存在FullGC等現象。
檢查網絡鏈路是否一切正常,例如是否存在丟包等網絡異常事件。
若上述物理資源均不存在瓶頸,可以檢查云消息隊列 RabbitMQ 版日志服務中的推送事件,根據RemoteAddress(客戶端IP)這一字段進行篩查。若每個IP的推送事件均符合預期,且持續推送,則代表該消費者仍然存活,擁有消費能力。
消費者代碼問題
檢查消費者代碼參數是否正確,是否按預期監聽指定隊列。
檢查同一個Channel是否監聽了多個隊列。若隊列間消息量差距較大,由于Channel共享QoS,可能會導致某些隊列的消費過程被其它隊列阻塞。
確認“丟失”消息所在隊列是否有堆積
若物理資源、消費者運行均正常,則可以查看消息所在隊列是否存在堆積。由于隊列模型的特點,堆積嚴重的隊列必須先將前面的消息消費完成后才會對后續消息進行推送。隊列堆積情況可以通過控制臺的監控指標,選取指定隊列進行查看。具體操作,請參見監控指標。
若您的實例是預付費系列的企業版、鉑金版、Serverless系列,還可以直接進入控制臺中的Dashboard進行查看,即下圖的Ready Message項。
確定存在消息堆積的情況,請參見消息堆積的可能原因及解決辦法。
查看該隊列QoS等參數設置是否合理
QoS參數會在很大程度上影響消費者的消費行為。消費者消費較慢,QoS設置較小,因此消息堆積,無法推送給消費者。消費者消費較慢,但是QoS設置較大,消息在服務端視角已經推送給消費者,但是由于消費者的消費能力低下,并未消費到這條消息。此時若消費者崩潰,則這條消息會重新入隊等待推送。
若QoS設置異常,且重推次數較少,這些已經被拉取到的消息頻繁被客戶端遺失,則可能導致該消息超過重推次數上限從而進入死信。
因此,請針對每個隊列的消費耗時,酌情設置QoS值。詳情請參見消費消息時需要注意什么?。
若上述方法均無法幫助您定位到消息“丟失”的原因,可以提交工單聯系技術支持。