2013-02-05 50 views
15

我有一個webapi,用於以隊列方式處理報表。是應用程序採取的步驟如下:如何在ASP.NET Web API中排列後臺任務

  • 接收內容
  • 內容映射到對象,並將其放置到隊列
  • 輪詢在隊列中的一個隊列中的待處理的物品
  • 過程項同時

我想使用實體框架來創建排隊的項目,如數據庫:

public class EFBatchItem 
{ 
    [Key] 
    public string BatchId { get; set; } 
    public DateTime DateCreated { get; set; } 
    public DateTime DateCompleted { get; set; } 
    public string BatchItem { get; set; } 
    public BatchStatus Status { get; set; } 
} 

我的問題是否有一種更有效的方法,使用NServiceBus,BlockingCollection或ConcurrentQeueue,而不是一直輪詢數據庫並逐一提取未決項目?我以前沒有用過隊列。

一個想法是創建一個任務隊列,並在一個單獨的線程處理所有未完成的任務。有點類似Most efficient way to process a queue with threads但我想確保我走的是最有效的路線。

編輯: 我在這裏有一個大問題是向用戶顯示進度的最佳方式。一旦用戶提交內容,他將被帶到一個新頁面,並可以通過批次標識符查看狀態。需要MSMQ還是NServiceBus以通知用戶?這似乎是REquest/Acknowledge/Push範例的變體?

+0

我的解決方案將是一個'周圍,你寫入數據庫的代碼部分lock'聲明。 – efkah

+0

感謝您的提示 - 沒有想到這一點,以後可能會導致很多問題:)有關排隊方法的任何想法?我應該打擾嘗試一個BlockingCollection,或只是恆定的數據庫輪詢?通過快速編輯更新了問題 – appsecguy

回答

23

恕我直言,你的ASP.NET Web API應用程序本身不應該運行這些後臺任務。它只應負責接收請求,並將其保存在隊列中(如您所示),並返回指示接收到的消息成功或失敗的響應。對於這種方法,您可以使用各種消息系統,例如RabbitMQ

至於通知,你有幾個選項。您可以擁有一個客戶端可以檢查處理是否完成的端點。或者,您可以提供您的客戶端可以訂閱的流API端點。這樣,客戶端不必輪詢服務器;服務器可以通知連接的客戶端。 ASP.NET Web API有這樣做的好方法。下面的博客文章介紹瞭如何:

你也可以考慮SignalR這種類型的服務器到客戶端的通知。

ASP.NET Web API應用程序難以執行後臺任務的原因是您有責任保持AppDomain處於活動狀態。這是一個麻煩,尤其是當您在IIS下託管時。下面的博客文章解釋了真正的好我的意思:

+0

好吧,後臺任務本質上是運行幾個ASP.NET函數來自動生成報告。你會推薦一個單獨的應用程序,並將內容傳遞給那個? – appsecguy

+1

@ pendraggon87你是什麼意思的「ASP.NET功能」? – tugberk

+0

實質上,我正在接收內容,然後使用Interop庫生成一個word文檔。我創建了一個Web應用程序,允許用戶在輸入大量信息後通過按鈕單擊來生成文檔,但我現在正在製作一個系統,通過接收JSON數據來生成報告。所以我寫了所有的代碼來編寫報告。您是否推薦我將該代碼放在單獨的應用程序中? – appsecguy

1

我喜歡@託德的解決方案。只是爲了完整起見,但有尚未提及的另一種選擇:

HostingEnvironment.QueueBackgroundWorkItem(cancellationToken => 
{ 
    // Some long-running job 
}); 

注:

「當ASP.NET有回收,它會通知後臺工作(通過設置的CancellationToken)和然後等待30秒才能完成工作,如果後面的工作沒有在這個時間框架內完成,工作就會神祕地消失。「

避免在這裏使用注入DbContext的服務方法,因爲這樣做不起作用。

來源: MariusSchulzStephenCleary