全部產品
Search
文件中心

Simple Message Queue (formerly MNS):訊息處理時間長度自適應

更新時間:Feb 19, 2025

本文介紹在訊息消費過程中實現訊息處理時間長度自適應的背景概念、應用情境及解決方案。

背景概念

  • 可見狀態:訊息處於可見狀態時,意味著訊息可以被消費者(接收和處理訊息的服務或應用程式)讀取和接收。

  • 不可見狀態:當消費者接收了一條訊息後,這條訊息會進入不可見狀態,意味著其他消費者在此期間無法接收到這條訊息,以免訊息被多個消費者同時處理。

  • 可見度逾時時間:是指從消費者接收訊息開始到允許其它消費者再次接收該訊息的時間段。

當消費者從隊列接收訊息時,訊息仍然保留在隊列中,但對其它消費者暫時不可見。暫時不可見狀態由可見度逾時機制控制,防止其它消費者在該訊息正在處理時重複處理同一條訊息。

關於可見度逾時時間的更多資訊,請參見可見度逾時時間(Visibility Timeout)

應用情境

輕量訊息佇列(原 MNS)的規範中,每條訊息都有預設的可見度逾時時間。消費者在接收到訊息後,立即開始計時。 如果消費者在可見度逾時時間內沒能處理完訊息,那麼訊息就有可能被其他消費者接收到並處理。計時的好處在於訊息處理完之後需要顯式地刪除訊息,如果消費者進程停止等異常情況發生,這條訊息還有機會被其他消費者處理。

一些使用者會將隊列的預設可見度逾時時間設定得比較長,以確保訊息在被消費者處理完之前不會逾時釋放。例如,隊列的可見度逾時時間是6個小時。一個消費者接收到了訊息M1,但是消費者在處理完訊息之後,進程發生了崩潰或者機器發生了重啟。那麼M1這條訊息至少在6個小時之後才會被另一個消費者接收到並處理。如果自己寫代碼處理故障,程式又會變得比較複雜。

在一些即時性要求比較高,並且又希望儘快響應每一條訊息的情境下,訊息消費需要實現以下目標:

  • 隊列的可見度逾時時間比較短。在發生了進程崩潰後,未處理完的訊息會在較短的可見度逾時時間內被某個消費者接收到並處理。

  • 訊息被處理時不能逾時。消費者處理訊息的過程中,耗時很有可能超過5分鐘,那麼訊息在被處理的過程中不能逾時。

解決方案

Simple Message Queue (formerly MNS)提供的C# SDK可以實現這樣的情境。具體的做法是,在消費者處理訊息的過程中,為訊息定期檢查是否需要做ChangeVisibility,消費者處理完之後依然是主動刪除訊息。

C# SDK的下載地址,請參見C++ SDK,如有Demo使用問題,可提交工單處理。

下面是對於程式的幾點說明:

  • 運行前需要填寫accessIdaccessKeyEndPoint

  • 變數說明:

    變數

    說明

    MessageMinimalLife

    訊息註冊時必須有的最少的Life長度。例如,訊息註冊的時候已經只剩下0.1秒的逾時時間了,註冊進來也來不及ChangeVisibility延長生命。所以,MessageMinimalLife是為了確保訊息能存活到被ChangeVisibility,您可以根據業務壓力自行設定。

    TimerInterval

    Manager內部的Timer的Interval。只需要確保在Message到達MessageMinimalLife之前,Timer會被啟動就足夠了。時間可以設定得較短(時間設定得較短會導致頻繁檢查)。

    QueueMessageVisibilityTimeout

    訊息的預設逾時時間,是Queue的屬性。每次ChangeVisibility的時候,會把訊息的可見度逾時時間設定為QueueMessageVisibilityTimeout,所以它的值需要大於TimerInterval+ MessageMinimalLife,以確保訊息不會逾時。

    MessageTimeout

    訊息在Manager中的逾時時間,例如某個消費者卡住了,訊息在5個小時之後依然沒有處理完畢(假設5個小時遠遠超出訊息的正常處理時間),那麼Manager就不會再為訊息做ChangeVisibility了,而是會放任訊息的Visibility逾時。

  • 流程說明:

    • 消費者在接收訊息之後,會先做註冊訊息,然後處理訊息,最後再調用Manager的刪除訊息(deleteMessage)。

    • Manager在訊息第一次註冊進來之後,調用ThreadPool調度一個ChangeVisibilityTask檢查是否需要ChangeVisibility,並且把Message添加到內部的messages列表中。

    • Manager內部的Timer,會定時調用Parallel啟動 ChangeVisibilityTask檢查訊息列表裡的所有訊息。

    • Manager.ChangeMessageVisibility (ChangeVisibilityTask)相關的具體操作,在流程圖裡有顯示。

      流程圖如下所示: