2016-08-03 66 views
7

我有一個Azure WebJob項目,我在本地開發機器上運行。它正在偵聽Azure服務總線消息隊列。沒有什麼像主題一樣,只是最基本的消息隊列。如何防止Azure webjob多次同時處理相同的消息

它正在多次接收/處理相同的消息,當收到消息時立即啓動兩次,然後在消息正在處理的同時間歇性地啓動。

問題:

  • 爲什麼我收到即時相同的消息多次?它似乎是在PeekLock應用之前重新獲取?
  • 即使郵件仍在處理中,郵件又是如何被重新收到?我可以設置PeekLock持續時間,或者以某種方式將消息鎖定爲僅處理一次
  • 如何確保隊列上的每條消息只處理一次?
  • 我希望能夠一次處理多個消息,多次不是同一個消息,因此將MaxConcurrentCalls設置爲1似乎不是我的答案,還是我誤解了該屬性?

我使用的是異步功能,簡單的注射器和一個自定義JobActivator,所以不是一個靜態無效的方法,我的函數簽名是:

public async Task ProcessQueueMessage([ServiceBusTrigger("AnyQueue")] MediaEncoderQueueItem message, TextWriter log) {...} 

的工作裏面,它是圍繞移動一些文件在blob服務上,以及從媒體服務呼叫(並等待)媒體編碼器。所以,雖然網絡作業本身並沒有做很多處理,但需要相當長的時間(15分鐘,對於某些文件)。

該應用程序正在啓動,當我將消息發送到隊列時,它會作出響應。但是,一旦收到消息接收的消息多次:

Executing: 'Functions.ProcessQueueMessage' - Reason: 'New ServiceBus message detected on 'MyQueue'.' 
Executing: 'Functions.ProcessQueueMessage' - Reason: 'New ServiceBus message detected on 'MyQueue'.' 

此外,雖然正在運行的任務(我看到來自媒體服務的功能輸出),它會得到另一個「複製」從隊列中。

最終在任務完成後,它仍然間歇地處理相同的消息。

+1

什麼是在隊列中指定的DeliveryCount和LockDuration? –

+0

我需要看看它。關於LockDuration的奇怪之處在於,它似乎幾乎立即收到了兩條消息,好像它並沒有鎖定它。我想知道這是否與我設置異步處理程序的方式有關? – AndrewP

+0

聽起來有點偏離。如果LockDuration沒有過期,代理將永遠不會給同一消費者提供相同的消息。我懷疑還有其他事情正在發生。你有可能在GitHub或BitBucket上共享repro? –

回答

7

我懷疑發生了什麼是以下幾點: 最大DurationLock可能是5分鐘。如果在5分鐘內處理完消息,則消息被標記爲已完成並從代理中刪除。否則,如果處理時間超過5分鐘(我們失去了對消息的鎖定),消息將重新出現,並且會再次消耗。您可以通過查看消息的DeliveryCount來驗證。

要解決該問題,可以在即將過期前使用BrokeredMessage.RenewLockAsync()續訂消息鎖定。

+0

我會檢查出這種方法,並會查看交付計數和持續時間鎖定。奇怪的是,它並不是每一次都在發生,而且它發生的時間似乎並沒有太大的一致性,而且它似乎也立即處理了兩次相同的信息。但是,多謝指出這個功能! – AndrewP

+0

@AndrewP如果你的工作拋出一個未處理的異常,並且在服務總線配置中有自動完成消息爲真,那麼它也可能是自動重試的情況。您可以通過簡單地在您的觸發器函數中拋出一個ex來測試,然後向該主題發佈一條消息 - 您應該看到一個消息檢測,直到最大重試次數。 – JoeBrockhaus

+0

默認情況下鎖不是自動更新的嗎?所以5分鐘後,如果處理仍在進行,鎖將自動更新。或者我錯過了什麼? – GETah

相關問題