使用SignalR實時Web應用程式
實時Web應用程式能夠實時地將伺服器端內容推送到連線的客戶端。對於ASP.NET開發人員,ASP.NET SignalR是一個向其應用程式新增實時Web功能的庫。它利用了多種傳輸方式,根據客戶端和伺服器的最佳可用傳輸自動選擇最佳可用傳輸。它利用了WebSocket,這是一種支援瀏覽器和伺服器之間雙向通訊的HTML5 API。
SignalR還提供了一個簡單的高階API,用於在ASP.NET應用程式中執行伺服器到客戶端RPC(在客戶端的瀏覽器中從伺服器端.NET程式碼呼叫JavaScript函式),以及為連線管理新增有用的鉤子,例如連線/斷開事件,分組連線和授權。
SignalR是對客戶端和伺服器之間進行實時工作所需的一些傳輸的抽象。一個SignalR連線開始為HTTP,然後提升到一個網頁套接字(如果可用)連線。WebSocket是SignalR的理想傳輸,因為它可以最有效地使用伺服器記憶體,具有最低的延遲,並具有最基本的功能(例如客戶端和伺服器之間的全雙工通訊),但它也有最嚴格的要求:WebSocket要求伺服器使用Windows Server 2012或Windows 8以及.NET Framework 4.5。如果不滿足這些要求,SignalR將嘗試使用其他傳輸來建立連線(如Ajax長輪詢)。
該SignalR API包含了客戶端和伺服器之間的通訊兩種型號:永久連線和樞紐。阿連線代表用於傳送單收件人,分組,或廣播訊息的簡單端點。一箇中心是於連線API,可讓您的客戶端和伺服器直接呼叫對方的方法建立了一個更高層的管道。
概觀
目標
- 使用SignalR從伺服器向客戶端傳送通知。
- 使用SQL Server擴充套件SignalR應用程式。
練習1:使用SignalR處理實時資料
雖然聊天通常用作示例,但您可以使用實時Web功能完成更多工作。每當使用者重新整理網頁以檢視新資料或頁面實現Ajax長輪詢以檢索新資料時,您都可以使用SignalR。
SignalR支援伺服器推送或廣播功能; 它自動處理連線管理。在用於客戶端 - 伺服器通訊的經典HTTP連線中,為每個請求重新建立連線,但SignalR提供客戶端和伺服器之間的持久連線。在SignalR中,伺服器程式碼使用遠端過程呼叫(RPC)呼叫瀏覽器中的客戶端程式碼,而不是我們今天所知的請求 - 響應模型。
在本練習中,您將配置Geek Quiz應用程式以使用SignalR顯示帶有更新指標的Statistics儀表板,而無需重新整理整個頁面。
任務1 - 探索極客測驗統計頁面
在此任務中,您將瀏覽應用程式並驗證統計資訊頁面的顯示方式以及如何改進資訊的更新方式。
開啟Visual Studio Express 2013 for Web並開啟位於Source \ Ex1-WorkingWithRealTimeData \ Begin資料夾中的GeekQuiz.sln解決方案。
按F5執行解決方案。將在登入頁面應該出現在瀏覽器中。
執行解決方案
單擊頁面右上角的“ 註冊”以在應用程式中建立新使用者。
註冊連結
在“ 註冊”頁面中,輸入“ 使用者名稱”和“ 密碼”,然後單擊“ 註冊”。
註冊使用者
應用程式註冊新帳戶,使用者通過身份驗證並重定向回顯示第一個測驗問題的主頁。
在新視窗中開啟Statistics頁面,並將Home頁面和Statistics頁面並排放置。
並排的窗戶
在主頁中,單擊其中一個選項來回答問題。
回答問題
單擊其中一個按鈕後,應顯示答案。
問題回答正確
請注意,“統計資訊”頁面中提供的資訊已過時。重新整理頁面以檢視更新的結果。
統計頁面
返回Visual Studio並停止除錯。
任務2 - 將SignalR新增到Geek測驗以顯示線上圖表
在此任務中,您將向解決方案新增SignalR,並在向伺服器傳送新答案時自動向客戶端傳送更新。
從Visual Studio 的“ 工具”選單中,選擇“ NuGet包管理器”,然後單擊“ 包管理器控制檯”。
在“ 程式包管理器控制檯”視窗中,執行以下命令:
Install-Package Microsoft.AspNet.SignalR
在Solution Explorer中,右鍵單擊GeekQuiz專案,選擇Add | 新建資料夾,並將其命名為Hubs。
右鍵單擊Hubs資料夾,然後選擇Add | 新資料夾。
新增新專案
在“ 新增新項”對話方塊中,選擇“ Visual C#” 網路| 在左窗格中的SignalR節點,從中心窗格中選擇SignalR Hub Class(v2),將檔案命名為StatisticsHub.cs,然後單擊Add。
新增新專案對話方塊
使用以下程式碼替換StatisticsHub類中的程式碼。
(程式碼片段 - RealTimeSignalR - Ex1 - StatisticsHubClass)
namespace GeekQuiz.Hubs { using Microsoft.AspNet.SignalR; public class StatisticsHub : Hub { } }
開啟Startup.cs並在Configuration方法的末尾新增以下行。
(程式碼片段 - RealTimeSignalR - Ex1 - MapSignalR)
public void Configuration(IAppBuilder app) { this.ConfigureAuth(app); app.MapSignalR(); }
開啟Services資料夾中的StatisticsService.cs頁面,並新增以下using指令。
(程式碼片段 - RealTimeSignalR - Ex1 - UsingDirectives)
using Microsoft.AspNet.SignalR; using GeekQuiz.Hubs;
要通知連線的客戶端更新,首先要檢索當前連線的Context物件。該中心物件包含的方法將訊息傳送到一個單一的客戶端或廣播到所有連線的客戶端。將以下方法新增到StatisticsService類以廣播統計資料。
(程式碼片段 - RealTimeSignalR - Ex1 - NotifyUpdatesMethod)
public async Task NotifyUpdates() { var hubContext = GlobalHost.ConnectionManager.GetHubContext<StatisticsHub>(); if (hubContext != null) { var stats = await this.GenerateStatistics(); hubContext.Clients.All.updateStatistics(stats); } }
開啟Controllers資料夾中的TriviaController.cs頁面,並新增以下using指令。using GeekQuiz.Services;
將以下突出顯示的程式碼新增到Post操作方法。
(程式碼片段 - RealTimeSignalR - Ex1 - NotifyUpdatesCall)
public async Task<IHttpActionResult> Post(TriviaAnswer answer) { if (!ModelState.IsValid) { return this.BadRequest(this.ModelState); } answer.UserId = User.Identity.Name; var isCorrect = await this.StoreAsync(answer); var statisticsService = new StatisticsService(this.db); await statisticsService.NotifyUpdates(); return this.Ok<bool>(isCorrect); }
開啟Views |中的Statistics.cshtml頁面 家庭資料夾。找到“ 指令碼”部分,並在該部分的開頭新增以下指令碼引用。
(程式碼片段 - RealTimeSignalR - Ex1 - SignalRScriptReferences)
@section Scripts { @Scripts.Render("~/Scripts/jquery.signalR-2.0.2.min.js"); @Scripts.Render("~/signalr/hubs"); ... }
注意
將SignalR和其他指令碼庫新增到Visual Studio專案時,程式包管理器可能會安裝一個版本比本主題中顯示的版本更新的SignalR指令碼檔案。確保程式碼中的指令碼引用與專案中安裝的指令碼庫的版本相匹配。
新增以下突出顯示的程式碼以將客戶端連線到SignalR集線器,並在從集線器收到新訊息時更新統計資料。
(程式碼片段 - RealTimeSignalR - Ex1 - SignalRClientCode)
@section Scripts { ... <script> ... var connection = $.hubConnection(); var hub = connection.createHubProxy("StatisticsHub"); hub.on("updateStatistics", function (statistics) { statisticsData = statistics; $("#correctAnswersCounter").text(statistics.CorrectAnswers); $("#incorrectAnswersCounter").text(statistics.IncorrectAnswers); showCharts(statisticsData); }); connection.start(); </script> }
在此程式碼中,您將建立一個Hub Proxy並註冊一個事件處理程式來偵聽伺服器傳送的訊息。在這種情況下,您將偵聽通過updateStatistics方法傳送的訊息。
任務3 - 執行解決方案
在此任務中,您將執行解決方案以驗證在回答新問題後使用SignalR自動更新統計資訊檢視。
按F5執行解決方案。
在新視窗中開啟Statistics頁面,並像在任務1中一樣並排放置Home頁面和Statistics頁面。
練習2:使用SQL Server進行擴充套件
擴充套件Web應用程式時,通常可以選擇擴充套件和擴充套件選項。向上擴充套件意味著使用更大的伺服器,具有更多資源(CPU,RAM等),而向外擴充套件意味著新增更多伺服器來處理負載。後者的問題是客戶端可以路由到不同的伺服器。連線到一臺伺服器的客戶端將不會接收從另一臺伺服器傳送的訊息。
您可以使用名為backplane的元件在伺服器之間轉發訊息來解決這些問題。啟用背板後,每個應用程式例項都會向背板傳送訊息,背板會將訊息轉發給其他應用程式例項。
SignalR目前有三種方式:
Windows Azure Service Bus。Service Bus是一種訊息傳遞基礎結構,允許元件傳送鬆散耦合的訊息。
SQL Server。SQL Server底板將訊息寫入SQL表。背板使用Service Broker進行有效的訊息傳遞。但是,如果未啟用Service Broker,它也可以使用。
Redis。Redis是一個記憶體中的鍵值儲存。Redis支援傳送/訂閱(“pub / sub”)模式以傳送訊息。
每條訊息都通過訊息匯流排傳送。訊息匯流排實現IMessageBus介面,該介面提供釋出/訂閱抽象。背板通過使用為該背板設計的匯流排替換預設IMessageBus來工作。
每個伺服器例項通過匯流排連線到背板。傳送訊息時,它會進入背板,背板會將其傳送到每個伺服器。當伺服器從背板接收訊息時,它會將訊息儲存在其本地快取中。然後,伺服器從其本地快取向客戶端傳遞訊息。
有關SignalR背板如何工作的更多資訊,請閱讀本文。
注意:在某些情況下,背板可能成為瓶頸。以下是一些典型的SignalR場景:
伺服器廣播(例如,股票程式碼):背板適用於此場景,因為伺服器控制訊息的傳送速率。
客戶端到客戶端(例如,聊天):在這種情況下,如果訊息數量與客戶端數量成比例,則背板可能是瓶頸; 也就是說,如果訊息的速率隨著更多客戶端的加入而成比例增長。
高頻實時(例如,實時遊戲):不建議在這種情況下使用背板。
在本練習中,您將使用SQL Server在Geek Quiz應用程式中分發訊息。您將在單個測試計算機上執行這些任務以瞭解如何設定配置,但為了獲得完整的效果,您需要將SignalR應用程式部署到兩個或更多伺服器。您還必須在其中一臺伺服器上或單獨的專用伺服器上安裝SQL Server。
任務1 - 瞭解場景
在此任務中,您將執行2個Geek Quiz例項,模擬本地計算機上的多個IIS例項。在這種情況下,當在一個應用程式上回答瑣事問題時,將不會在第二個例項的統計頁面上通知更新。此模擬類似於將應用程式部署在多個例項上並使用負載平衡器與它們進行通訊的環境。
開啟位於Source / Ex2-ScalingOutWithSQLServer / Begin資料夾中的Begin.sln解決方案。載入後,您會在Server Explorer上注意到該解決方案有兩個結構相同但名稱不同的專案。這將模擬在本地計算機上運行同一應用程式的兩個例項。
開始解決方案模擬Geek測驗的2個例項
右鍵單擊解決方案節點並選擇“ 屬性”,開啟解決方案的屬性頁面。在“ 啟動專案”下,選擇“ 多個啟動專案”並將兩個專案的“操作”值更改為“ 啟動”。
啟動多個專案
按F5執行解決方案。該應用程式將在不同的埠啟動兩個Geek Quiz例項,模擬同一應用程式的多個例項。將其中一個瀏覽器固定在螢幕右側,另一個固定在螢幕右側。使用您的憑據登入或註冊新使用者。登入後,將Trivia頁面保留在左側,然後轉到右側瀏覽器中的Statistics頁面。
在左側瀏覽器中開始回答問題,您會注意到右側瀏覽器中的“ 統計”頁面未更新。這是因為SignalR使用本地快取在其客戶端上分發訊息,並且此方案模擬多個例項,因此不在它們之間共享快取。您可以通過測試相同的步驟但使用單個應用來驗證SignalR是否正常工作。在以下任務中,您將配置以跨例項複製訊息。
返回Visual Studio並停止除錯。
任務2 - 建立SQL Server資料庫
在此任務中,您將建立一個數據庫,作為Geek Quiz應用程式的資料來源。您將使用SQL Server物件資源管理器瀏覽您的伺服器並初始化資料庫。此外,您將啟用Service Broker。
在Visual Studio中,開啟選單檢視並選擇SQL Server物件資源管理器。
通過右鍵單擊“ SQL Server”節點並選擇“ 新增SQL Server …”選項,連線到LocalDB例項。
將SQL Server例項新增到SQL Server物件資源管理器
將伺服器名稱設定為(localdb)\ v11.0,並將Windows身份驗證保留為身份驗證模式。單擊“ 連線”繼續。
連線到LocalDB
現在您已連線到LocalDB例項,您將需要建立一個名為SignalR的SQL Server資料庫。為此,請右鍵單擊“ 資料庫”節點,然後選擇“ 新增新資料庫”。
新增新資料庫
將資料庫名稱設定為SignalR,然後單擊“ 確定”以建立它。
建立SignalR資料庫
注意:您可以為資料庫選擇任何名稱。
要從背板更有效地接收更新,建議為資料庫啟用Service Broker。Service Broker為SQL Server中的訊息傳遞和排隊提供本機支援。背板也可以在沒有Service Broker的情況下工作。通過右鍵單擊資料庫並選擇“ 新建查詢”來開啟新查詢。
開啟新查詢
要檢查Service Broker是否已啟用,請查詢sys.databases目錄檢視中的is_broker_enabled列。在最近開啟的查詢視窗中執行以下指令碼。
SELECT [name], [service_broker_guid], [is_broker_enabled] FROM [master].[sys].[databases]
查詢Service Broker狀態
如果資料庫中is_broker_enabled列的值為“0”,請使用以下命令啟用它。將替換為您在建立資料庫時設定的名稱(例如:SignalR)。
ALTER DATABASE <YOUR-DATABASE> SET ENABLE_BROKER
啟用Service Broker
注意:如果此查詢似乎死鎖,請確保沒有應用程式連線到資料庫。
任務3 - 配置SignalR應用程式
在此任務中,您將配置Geek Quiz以連線到SQL Server後臺。您將首先新增SignalR.SqlServer NuGet包並將連線字串設定為您的元件資料庫。
從Tools > NuGet Package Manager開啟Package Manager控制檯。確保在“ 預設專案”下拉列表中選擇了GeekQuiz專案。鍵入以下命令以安裝Microsoft.AspNet.SignalR.SqlServer NuGet包。
Install-Package Microsoft.AspNet.SignalR.SqlServer
重複上一步,但這次是專案GeekQuiz2。
要配置SQL Server元件,請開啟GeekQuiz專案的Startup.cs檔案,並將以下程式碼新增到Configure方法中。將替換為您在建立SQL Server後臺時使用的資料庫名稱。對GeekQuiz2專案重複此步驟。
(程式碼片段 - RealTimeSignalR - Ex2 - StartupConfiguration)
public class Startup { public void Configuration(IAppBuilder app) { var sqlConnectionString = @"Server=(localdb)\v11.0;Database=<YOUR-DATABASE>;Integrated Security=True;"; GlobalHost.DependencyResolver.UseSqlServer(sqlConnectionString); this.ConfigureAuth(app); app.MapSignalR(); } }
既然兩個專案都配置為使用SQL Server元件,請按F5同時執行它們。
同樣,Visual Studio將在不同的埠啟動兩個Geek Quiz例項。將其中一個瀏覽器固定在螢幕右側,另一個固定在螢幕右側,然後使用您的憑據登入。將Trivia頁面保留在左側,然後轉到右側瀏覽器的Statistics頁面。
開始在左側瀏覽器中回答問題。這次,由於背板,統計頁面會更新。在應用程式之間切換(統計資訊現在位於左側,Trivia位於右側)並重複測試以驗證它是否適用於兩個例項。後臺用作每個連線的伺服器的訊息的共享快取,並且每個伺服器將訊息儲存在它們自己的本地快取中以分發給連線的客戶端。
返回Visual Studio並停止除錯。
SQL Server後臺自動在指定的資料庫上生成必要的表。在SQL Server物件資源管理器面板中,開啟為背板建立的資料庫(例如:SignalR)並展開其表。您應該看到以下表格:
背板生成表
右鍵單擊SignalR.Messages_0表,然後選擇“ 檢視資料”。
檢視SignalR背板訊息表
在回答問題時,您可以看到傳送到Hub的不同訊息。後臺將這些訊息分發給任何連線的例項。