2013-10-28 32 views
1

我有一個工作人員角色處理隊列中的項目。它基本上是一個無限循環,它將項目從隊列中彈出並異步處理它們。工作人員角色過程 - 配置值輪詢

我有兩個配置設置(PollingIntervalMessageGetLimit),我希望工人角色在更改時拾取(因此不需要重新啓動)。

private TimeSpan PollingInterval 
{ 
    get 
    { 
     return TimeSpan.FromSeconds(Convert.ToInt32(RoleEnvironment.GetConfigurationSettingValue("PollingIntervalSeconds"))); 
    } 
} 

private int MessageGetLimit 
{ 
    get 
    { 
     return Convert.ToInt32(RoleEnvironment.GetConfigurationSettingValue("MessageGetLimit")); 
    } 
} 

public override void Run() 
{ 
    while (true) 
    { 
     var messages = queue.GetMessages(MessageGetLimit); 

     if (messages.Count() > 0) 
     { 
      ProcessQueueMessages(messages); 
     } 
     else 
     { 
      Task.Delay(PollingInterval); 
     } 
    } 
} 

問題:

在高峯時段,while循環可以運行一對夫婦次每秒。這意味着它將每天查詢配置項目高達100,000次。

這是有害的還是低效的?

回答

2

預先聲明,我沒有使用過RoleEnvironments。

GetConfigurationSettingValue的MDSN文檔指出從磁盤讀取配置。 http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.serviceruntime.roleenvironment.getconfigurationsettingvalue.aspx。所以經常打電話肯定會很慢。

MSDN文檔還顯示在設置更改時會觸發事件。 http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.serviceruntime.roleenvironment.changed.aspx。您可以使用此事件僅在實際更改時重新加載設置。

這裏是一個(未經測試,未編譯)的方法。

private TimeSpan mPollingInterval; 
private int mMessageGetLimit; 

public override void Run() 
{ 
    // Refresh the configuration members only when they change. 
    RoleEnvironment.Changed += RoleEnvironmentChanged; 

    // Initialize them for the first time 
    RefreshRoleEnvironmentSettings(); 

    while (true) 
    { 
     var messages = queue.GetMessages(mMessageGetLimit); 

     if (messages.Count() > 0) 
     { 
      ProcessQueueMessages(messages); 
     } 
     else 
     { 
      Task.Delay(mPollingInterval); 
     } 
    } 
} 

private void RoleEnvironmentChanged(object sender, RoleEnvironmentChangedEventArgs e) 
{ 
    RefreshRoleEnvironmentSettings();  
} 

private void RefreshRoleEnvironmentSettings() 
{ 
    mPollingInterval = TimeSpan.FromSeconds(Convert.ToInt32(RoleEnvironment.GetConfigurationSettingValue("PollingIntervalSeconds"))); 
    mMessageGetLimit = Convert.ToInt32(RoleEnvironment.GetConfigurationSettingValue("MessageGetLimit")); 
} 
3

約翰的回答是一個很好的使用環境改變/變更事件,而重新修改您的設置,但我認爲也許是一個更好的方法是你要使用指數回退的政策,讓您的投票更高效。通過使代碼行爲更加智能化,您將會減少您調整代碼的頻率。請記住,每次更新這些環境設置時,都必須將其展開到所有實例,這可能需要一些時間,具體取決於您運行的實例數。此外,你正在向這一步邁進,一個人必須參與。

您正在使用Windows Azure存儲隊列,這意味着每次您的GetMessages執行時,它都會調用服務並檢索0個或更多消息(直至您的MessageGetLimit)。每次它都會要求您收取一筆交易費用。現在,明白交易確實很便宜。即使每天100,000個交易也是0.01美元/天。但是,請不要低估循環的速度。 :)你可能會得到更多的吞吐量,如果你有多個工作者角色實例會增加(儘管與實際運行實例本身相比,仍然是非常少的錢)。

更有效的途徑是將指數退避方法放在隊列中讀取消息。看看這個帖子馬爾滕在一個簡單的例子:http://www.developerfusion.com/article/120619/advanced-scenarios-with-windows-azure-queues/。通過基於隊列深度的自動縮放工作角色來結合後退方法,您將獲得一種解決方案,該方案對人工調整設置的依賴較少。輸入實例計數的最小值和最大值,根據下一次請求輸入消息的次數調整消息的數量,等等。這裏有很多選項可以減少您的參與並有一個有效的系統。另外,您可能會看到Windows Azure服務總線隊列,因爲它們實現了長輪詢,因此在等待工作進入隊列時會導致更少的事務處理。

+0

我實際上實現了這一點,它造成了更多的問題,而不是幫助。隨着隊列,我實現了一些預期延遲的小型工作。不幸的是,在退出投票時,我遇到了一個情況,一個客戶會一次發送30個請求/微型工作,而我一分錢也不願意每月節省幾美元,而且這些請求被不必要的門限所拖延。 –

+0

延遲只是您願意等待處理郵件的最長時間。如果那是2秒鐘,它不應該等待超過2秒。系統應在處理完消息後立即檢查,看看是否有另一個消息再開始退出。如果您始終在尋找即時響應,那麼請保持緊密的循環或查看除隊列以外的其他內容。我會同意,在某些情況下這可能是一分錢捏,但是要求經常需要人工干預的事情也不好。這最終會花費更多。 – MikeWo

相關問題