2016-05-13 82 views
1

因此,我有一個SPA(單頁應用程序),AngularJS作爲前端,.NET Web API作爲後端(C#)。我需要在某些用戶操作時生成SQL Server Reporting Services(SSRS)報告,即選擇一些數據並按下按鈕。這裏是我現有的架構的一個粗略的說明:RabbitMQ與AngularJS/.NET Web API應用程序的架構

FRONT END     BACK END     SSRS Report 
==========    =========     =========== 
**AngularJS Web page**-->**.NET Web API controller**-->**Intermediary class (passes arguments to report)** -->**Generate report and save to file** 

這工作,但問題是,而正在生成報表的應用程序必須坐在那裏,等待他們完成並在此期間,用戶可以」不要做任何事情。如果有很多報告需要創建,例如100多個報告,則可能需要一兩分鐘的時間,這對我來說是不可接受的。

所以這就是RabbitMQ進來的地方。我想到的是.NET Web API控制器向服務器發送消息,一旦服務器收到它,就會對上面的中間類執行一個調用,報告,然後回覆給客戶,讓他們知道報告已經生成。我想我需要使用RPC方案,所以我已經在RabbitMQ網站上完成了相應的教程,看起來很簡單。

雖然我不知道,但這就是我的問題所在,就是如何從.NET Web API應用程序啓動客戶端和服務器。坦率地說,我現在有點失落,因爲這是我第一次使用任何類型的消息傳遞的真實體驗,我不太清楚如何處理它,架構明智。如果我可以在頭腦中詳細瞭解整個事情的工作方式,我可以從那裏編寫代碼,但是現在我很難想象如何構建應用程序。

所以,問題:

  1. 我如何開始從.NET Web API控制器的RabbitMQ服務器和客戶端?服務器和客戶端應該是類庫還是控制檯應用程序,還是其他的東西?

  2. 我設想的體系結構會起作用還是有更好的方法?

  3. 任何關於如何接近我試圖完成的一般建議將不勝感激。

回答

3
  1. 的RabbitMQ服務器之前引入的新HostingEnvironment.QueueBackgroundWorkItem是不是你從控制器開始的東西 - 它始終運行。從控制器發送消息到rabbitmq服務器。另一方面,另一個應用程序(Windows服務,控制檯應用程序或者Linux上的單聲道服務)會監聽這些消息並處理它們。 RabbitMQ服務器僅管理端點之間的發送消息。在你的情況下,處理來自你的控制器的消息的應用程序也一直在運行(使它成爲windows服務是合理的)。

  2. 這樣的架構將工作是的。 RabbitMQ雖然可能是一種矯枉過正的情況 - 它對於多服務器,高負載情況更是如此。如果負載較低,並且所有應用程序都在同一臺服務器上,則可以使用其他工具(如hangfire.io,MSMQ,或者甚至只是在Web服務器進程中運行後臺任務,如另一個答案所示)。如果簡單的工具可以做你的工作 - 爲什麼不。

  3. 生成報告時,不要始終保持客戶端(瀏覽器)與服務器之間的連接。只需將任務放入兔子隊列進行處理(或以其他方式開始生成報告)並返回。然後,如果作業已完成,則定期從客戶端進行輪詢,或(更好地)通過websocket連接通知客戶端。這當然是報告生成可能需要一些時間(超過30秒)。

更新:更多關於整體架構。

  • RabbitMQ服務器作爲Windows服務運行,與Windows一起啓動。
  • 當您通過web api接收到報告生成請求時 - 您將GenerateReport消息與所有需要的信息一起放入,然後返回(不等待報告生成)。如果您將報告存儲在數據庫中,那麼它們是持久的 - 在數據庫中創建關於報告請求的記錄。否則 - 在內存中保存關於待處理報告的信息(以便您知道當前正在生成X報告)。在理想情況下,您也可以通過Web套接字在客戶端和服務器之間建立持久連接。如果是這種情況 - 您將實時通知用戶有關報告生成狀態。否則 - 用戶將不得不頻繁輪詢服務器。
  • 另一方面是由您編寫的Windows服務,它也與Windows服務器一起啓動。它監聽GenerateReport消息並開始生成。可以有多個這樣的服務,或者你可以在一個服務中有多個訂閱 - 這將均勻地在多個服務之間分配工作負載。報告生成期間 - 發佈ReportProgress消息。完成後 - 更新數據庫中的報告(如果持續存在)併發布ReportDone消息。 Web Api服務中的後臺線程偵聽此類消息。如果你有websockets連接 - 你只需將這些消息傳遞給客戶端,這樣他就可以實時查看報告生成進度。否則 - 更新數據庫或內存中的結構,以便下次客戶端將輪詢報告狀態時 - 您將返回一些內容。
  • 如果出現問題 - 沒有問題(如果你堅持報告數據庫)。在啓動時,您的生成服務將檢查數據庫中是否有未決報告並生成它們。如果客戶端在報告生成過程中斷開連接(從網站) - 仍然沒有問題,當他返回報告時就會準備就緒,並可以從數據庫提供服務。如果web api服務崩潰 - 仍然沒有問題。
+0

1. @Evk,你所描述的與遠程過程調用(RPC)模式相當,其中有一個客戶端和一個服務器,前者向後者發送消息,然後接收消息(結果)?這在這裏有更詳細的描述:https://www.rabbitmq.com/tutorials/tutorial-six-dotnet.html。 – lukegf

+0

2.如果是這樣,您稱爲「另一個應用程序偵聽這些消息並處理它們」對應於RPC模式中的客戶端嗎?另外,您說RabbitMQ服務器始終在運行,即使它不應該從控制器啓動,也必須啓動它。這是如何運作的?誰啓動服務器?換句話說,假設我編碼服務器,就像上面的RabbitMQ站點上的示例一樣。那之後我該怎麼處理它?我假設我必須將它部署在某處並以某種方式對其進行配置,以便它始終處於運行狀態。客戶同樣的問題。 – lukegf

+1

@ user452103兔子只是一個或多個應用程序之間的消息總線(中介,代理)。在你的情況下,一個應用程序是你的asp.net web api服務。另一個應用程序生成報告(例如 - 單獨的控制檯或Windows服務應用程序)。如果使用RPC模式,則應用程序A(web api)會嚮應用程序B(windows服務)發送消息,要求生成報告。然後它會等待,直到應用程序B將返回一條帶有操作結果的消息。至於誰開始兔子。在Windows上,您可以將兔子作爲服務運行 - 然後與Windows一起啓動。 – Evk

2

您是否嘗試過使用在.NET 4.5切換到RabbitMQ的

HostingEnvironment.QueueBackgroundWorkItem(cancellationToken => 
{ 
    return Task.Factory.StartNew(() => 
    { 
     // Generate report and save to file 
    }, cancellationToken); 
}); 
+0

不,我沒有。這是我第一次聽說它。它究竟做了什麼? – lukegf

+1

「安排可在後臺運行的任務,與任何請求無關。」和[這裏是博客文章](https://blogs.msdn.microsoft.com/webdev/2014/06/04/queuebackgroundworkitem-to-reliably-schedule-and-run-background-processes-in-asp-net/ )與更多細節。 – Nasreddine

+0

聽起來像它有一些嚴重的限制,但。例如:「如果排隊的項目太多,無法在90秒內完成,ASP.NET運行時將卸載AppDomain而不等待工作項完成。」這對我來說是一種破壞,因爲我可能會有這麼多的報告,他們很容易就會花費超過90秒的時間來生成。 – lukegf