全部產品
Search
文件中心

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

更新時間:Jun 30, 2024

本文介紹如何使訊息處理時間長度自適應。

背景資訊

Message ServiceMNS的規範中,每條訊息都有個預設的VisibilityTimeout,Worker在接收到訊息後,Timeout就開始計時了。 如果Worker在Timeout時間內沒能處理完訊息,那麼訊息就有可能被其他Worker接收到並處理。

Timeout計時的好處在於訊息處理完之後需要顯式地DeleteMessage,那麼如果Worker進程停止等情況發生,這條訊息還有機會被其他Worker處理。

一些使用者會將隊列的預設VisibilityTimeout設定得比較長,以確保訊息在被Worker處理完之前不會逾時釋放。

問題描述

隊列的VisibilityTimeout是6個小時。

一個Worker接收到了訊息M1,但是Worker在處理完訊息之後,進程發生了Crash或者機器發生了重啟。

那麼M1這條訊息至少在6個小時之後才會被另一個Worker接收到並處理。而自己寫代碼處理Failover的情況的話,程式又會變得比較複雜。

目標

在一些即時性要求比較高,並且又希望儘快響應每一條訊息的情境下,使用者會希望:

  • 隊列的VisibilityTimeout比較短,例如5分鐘。在發生了進程Crash後,最多5分鐘,未處理完的訊息就會被某個Worker接收到並處理。
  • Worker處理訊息的過程中,耗時很有可能超過5分鐘,那麼訊息在被處理的過程中不能逾時。

解決方案

BestPractice的C# Demo可以實現這樣的情境。Demo下載地址為Sample。具體的做法是,在Worker處理訊息的過程中,為訊息定期檢查是否需要做ChangeVisibility,Worker處理完之後依然是主動deleteMessage。

遇到Demo使用問題,可提交工單處理。

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

  • 運行前需要填寫accessId、accessKey、EndPoint。
  • 變數說明:
    • MessageMinimalLife是訊息註冊時必須有的最少的Life長度。需要這個的原因是,例如訊息register的時候已經只剩下0.1秒的逾時時間了,註冊進來也來不及ChangeVisibility延長生命。所以,MessageMinimalLife是為了確保訊息能活到被ChangeVisibility,使用者可以自己根據業務壓力來設定。
    • TimerInterval是Manager內部的Timer的Interval。只需要確保在Message到達MessageMinimalLife之前,Timer會被啟動就足夠了。時間可以設定得比較短(檢查得就比較頻繁)。
    • QueueMessageVisibilityTimeout是Sample裡Message的預設逾時時間,是Queue的屬性。Sample裡每次ChangeVisibility的時候,會把訊息的VisibilityTimeout設定為QueueMessageVisibilityTimeout,所以它的值需要大於TimerInterval+ MessageMinimalLife,以確保訊息不會逾時。
    • MessageTimeout是Message在Manager裡面的逾時時間,例如某個Worker卡住了,訊息在5個小時之後依然沒有處理完畢(假設5個小時遠遠超出訊息的正常處理時間),那麼Manager就不會再為訊息做ChangeVisibility了,會放任訊息的Visibility逾時。
  • 流程說明:
    • Worker在ReceiveMessage之後,會先做RegisterMessage,然後處理Message,最後再調用Manager的deleteMessage。
    • Manager在訊息第一次註冊進來之後,調用ThreadPool調度一個ChangeVisibilityTask檢查是否需要ChangeVisibility,並且把Message加到內部的messages列表中。
    • Manager內部的Timer,會定時調用Parallel啟動 ChangeVisibilityTask檢查messages列表裡的所有message。
    • Manager.ChangeMessageVisibility (ChangeVisibilityTask)相關的具體事情,在流程圖裡有顯示。流程圖如下:處理時間長度自適應