2009-04-08 97 views
0

我有一個執行寫入到數據庫每次請求頁面時的應用程序。這個數據庫寫入不是時間關鍵,所以出於性能原因,我使用MSMQ排隊對象。當然,我必須有一些讀取隊列和處理請求,所以我寫了一個類,看起來與此類似:ASP.NET線程+設計問題

public class QueueProcessor { 
    public void Start() 
    { 
     // Create background thread to run ProcessInternal() 
    } 

    public void Stop() 
    { 
     // Stop the previously created thread 
    } 

    public void ProcessInternal() 
    { 
     while (runnable) 
     { 
      // check queue for messages, process them one at a time, 
      // then wait indefinitely for more messages 
     } 
    } 
} 

現在,因爲該網站在本質上是相當小的,我真的不要」我不想爲部署例程添加一個Windows服務,所以我現在正在做的是在Application_Start事件中創建一個新的QueueProcessor並在那裏啓動它。我的想法是,該線程將在應用程序的生命週期中運行,並且如果應用程序被IIS終止,那麼只有在下一次有人訪問某個頁面時它纔會重新啓動。

爲了防止長時間的空閒,因爲應用程序已被IIS終止而未處理排隊的消息,我建立了一個wget請求,在網站的某個頁面上每隔幾分鐘執行一次,從而使應用程序保持活動狀態並確保後臺線程將繼續運行。

我的問題是,我沒有看到這樣的設計,很多時候,如果有任何與它的潛在的問題我不知道?

編輯:

關於這個問題做一些閱讀後,我發現,這種方法(以及類似的,如緩存清除回調函數)的主要問題是他們被要求的功能類型在可伸縮性方面執行。例如,如果您正在進行大規模更新或其他操作,那麼您顯然不希望該任務在所有Web服務器上運行 - 這樣就會產生衝突的更新和潛在的數據丟失。

但是,我非常特定的情況下,線程正在處理由坐在該服務器的消息隊列服務器只收到請求。因此,如果我將這個應用程序擴展爲5個服務器,每個線程都會毫無問題地處理每個服務器排隊的消息。同樣,數據庫中記錄的順序並不那麼重要,以至於在一個小的時間間隔內來自不同服務器的一些類似請求會成爲問題,所以我仍然認爲這個解決方案對我的問題是合理的。

回答

1

我已經用在一些網站上,我保持着毫不費力類似的計劃。要注意的主要事情是確保您正確捕獲線程中的所有異常。你不想擁有的是在你不知道的情況下死亡的線程,然後當應用程序回收時再次靜默地重新啓動。

1

我相信建立wget的要求是不低於部署Windows服務要容易得多。 除此之外,我沒有看到任何具體問題。如果可靠性和準確的時間不重要,這將工作。

+0

wget的部分是額外的,而不是真正需要。正如另一張海報所提到的,只要我抓住/處理該線程上的所有異常,就沒有機會過早死亡,並且由於空閒的應用程序殺死意味着沒有排隊的流量,所以我真的也沒關係。 – Chris 2009-04-09 14:20:45

1

雖然我不認爲這是一個好主意,但Jeff和Co. seem to use similar hackery要避免在這個網站上使用Windows服務(並且Joel對於FogBugz也這樣做)。由於規模和性能在這裏得到了很好的證明 - 它的確看起來合理可行。

+0

事實上,他們不再使用這個技巧,閱讀Jeff的最後評論(迴應Joe的問題,在頁面底部) – 2009-04-09 02:09:48