2013-01-22 43 views
4

我有一個天藍色的存儲表,其中有一些任務要在某個時間由工作角色完成。例如:Azure工作者角色 - 後臺任務計劃

 Task 1: -> run every 5 min 
     Task 2: -> run every 1 min 
     Task 3: -> run every 10 min 
     Task 4: -> run every 1 min 
     Task 5: -> run every 5 min 
     ........................... 
     Task 1000: -> run every 1 min 

這是正確的做法: 每個任務都有一個名爲「LASTRUN」一欄的日期時間。還有另一個名爲「RunEvery」的專欄,用於存儲執行任務的時間。輔助角色遍歷所有任務,並不斷爲每個任務檢查列「LASTRUN」用以下方法:

 DateTime currentTime = DateTime.Now; 
     if (currentTime >= (myTask.LastRun + myTask.RunEvery)) 
     { 
      myTask.Execute() 
     } 
     else 
     { 
      Check.Next.Task.InTable(); 
     } 

那麼如果輔助角色連續運行消耗資源?我們如何能夠挖掘資源?或者我能否以更好的方式實現這一點?你有什麼建議?

+0

幾天前,我可能寫了你正在尋找的東西。它是一個依賴Azure表的c#調度程序,專爲低事務消耗(每50個計劃任務的3個表存儲事務)而設計,可用於多個角色實例的上下文中。計劃任務是「transactionnal」,這意味着你必須調用.Handled();當任務完成時(否則它會在「x」小時後再次被觸發)。如果有興趣,我仍然需要清理代碼,然後我可以在github上發佈它。 – uzul

+0

絕對有興趣!接縫有趣!請讓我知道什麼時候準備好了!提前致謝! –

+0

我正在發佈它。 – uzul

回答

12

添加到@Simon Munro的答案:另一種實現任務調度而無需外部調度程序依賴項的方法是在您的輔助角色中使用Quartz庫(http://quartznet.sourceforge.net/)。我已經在一個項目中使用它,它工作得非常好。就調度任務而言,它給你很大的靈活性。您仍需要使用blob租賃和Windows Azure隊列來處理多個工作角色實例之間的併發問題。

UPDATE:受此啓發,我寫了一篇關於相同的博客文章,您可以在這裏閱讀:http://gauravmantri.com/2013/01/23/building-a-simple-task-scheduler-in-windows-azure/

+2

「另一種實現沒有外部調度程序依賴的任務調度的方法是使用Quartz庫」。 Quartz庫聽起來像是一個外部依賴項。 – uzul

+0

可能是我應該澄清我的意思是外部依賴 - 我的意思是一個外部服務(如西蒙提到的aditi雲服務)。 Quartz庫被集成到您的項目中,並且是您項目的一部分。 –

+0

我看到:)偉大的文章的方式。 – uzul

3

滾動自己的調度不是一個好主意。除非您鎖定正在閱讀的數據,否則會遇到各種問題。例如,您可以擴展到幾十或幾百個相同的工作人員角色,並確保每個作業僅運行所需的次數。您可能需要使用諸如leases on blob storage之類的東西來「鎖定」您的任務。

儘管您正在查看的工作數量可能會很高,但一個好方法是使用新發布的aditi cloud services之類的cron作業服務,如setcronjob。您將您的任務作爲Web服務來實現,並將它們連接到外部服務。

就資源利用率而言,每隔幾分鐘觸發一次事件的計時器就不會佔用太多資源。您可以有一個執行任務的單個線程,從隊列中讀取(即使是ConcurrentQueue),因此您一次只能執行一個任務(如果精確的時間不是問題)。其他線程/定時器/事件可以將任務添加到隊列中。

1

您目前的方法看起來好像不會擴展到多個工作角色。

我會建議一些改動:

  1. 使用存儲隊列到準備執行任務的店。準備好運行時向Queue添加消息,這樣其他工作人員角色可以參與執行任務。您也可以使用隊列來隱藏任務,直到它也可以運行。

  2. 當您正在閱讀時鎖定blob資源&更新您的日程安排表,這種方式只有一個工作人員角色可以安排任務。

請記住,您的任務可能(在極少數情況下)會執行兩次,因此請嘗試設計。

爲避免頻繁地觸發隊列或表,請考慮如果您的隊列&時間表爲空,請以Thread.Sleep指數退避。

This blog包含更多的細節,可能有助於您的實施。

1

儘管Gaurav Mantri寫了一篇很好的文章,展示瞭如何以安全的方式將Quartz與Azure存儲Queue/Table/Blobs連接起來,但這種解決方案並不符合我正在開發的應用程序的要求。同時使用Queue/Blobs/Table可能會使Azure交易成本變得非常昂貴,這是我的主要擔憂之一。

我目前正在開發一個Azure應用程序,需要安排大量的任務,所以我幾天前寫了自己的「家」解決方案,但它離石英的質量還很遠,到目前爲止只是一個原型,但尚未經過正確測試,但它似乎對我很好。

設計目標

  • 優化存儲交易儘可能多地。這僅使用RangeQueries和BatchOperations完成,事務儘可能分組。計劃和提取只能使用3個存儲事務完成50個任務。
  • 每個ScheduledTask必須正確「提交」(否則將在稍後再次啓動)。
  • 簡單和非侵入式API
  • 調度類線程安全的,應該是跨多個實例

併發問題是使用了刪除操作來解決,如果一個任務是在已經離隊,將失敗的整體安全同時。 (內部處理)

我剛剛發佈了項目here。這本來並不意味着要公佈,被認爲是這樣。請讓我知道您何時會發現錯誤。

0

如果任務不需要頻繁運行,一種方法是創建一個Azure SQL表併爲每個執行生成一行。作爲列,你應該有執行時間和應該運行的任務的一些標識符。因此,如果一項任務每天運行一次,並且想要保持運行5年,則會放入5 * 365行。

工作人員將運行無限循環,從該表中選擇執行時間小於當前時間但尚未執行的任務。對於多個工作人員,您需要處理事務以確保每個任務只由一名工作人員執行。

或者你甚至可以對Azure Service Bus使用類似的機制。服務總線支持計劃交付,並且消息生存時間似乎沒有上限。通過服務總線,您可以簡單地將每個計劃執行的消息推送到執行時間的交貨時間。工作人員然後會從隊列中彈出消息。

使用服務總線的一個好處是您可以輕鬆地添加更多的工作人員,而無需擔心他們會開始處理相同的任務。

0

可能會回答一個老問題。但是不要像圖書館那樣使用重量級Cron(其中很多),可能值得花一點時間學習Rx The Reactive Extensions,並在那裏使用Timer。A simple example from the Rx wiki