在 Azure Web 角色中使用 SignalR 性能計數器
作者:Luke Latham
警告
本檔不適用於最新版本的 SignalR。 看看 ASP.NET Core SignalR。
SignalR 性能計數器可用來監視應用程式在 Azure Web 角色中的效能。 計數器會由Microsoft Azure 診斷 擷取。 您可以使用 signalr.exe 在 Azure 上安裝 SignalR 性能計數器,這是用於獨立或內部部署應用程式的相同工具。 由於 Azure 角色是暫時性的,因此您會設定應用程式,以在啟動時安裝及註冊 SignalR 性能計數器。
必要條件
- Visual Studio 2015 或 2017
- Microsoft Azure SDK for Visual Studio 注意:安裝 SDK 之後重新啟動您的電腦。
- Microsoft Azure 訂用帳戶:若要註冊免費的 Azure 試用版帳戶,請參閱 Azure 免費試用。
建立公開 SignalR 性能計數器的 Azure Web 角色應用程式
開啟 Visual Studio。
在 Visual Studio 中,選取 [檔案]>[新增]>[專案]。
在 [新增專案] 對話框中,選取左側的 [Visual C#>Cloud] 類別,然後選取 [Azure 雲端服務] 範本。 將應用程式 命名為 SignalRPerfCounters ,然後選取 [ 確定]。
注意
如果您沒有看到 雲端 範本類別或 Azure 雲端服務 範本,您必須安裝適用於 Visual Studio 2017 的 Azure 開發 工作負載。 選擇 [新增專案] 對話框左下方的 [開啟 Visual Studio 安裝程式 連結,以開啟 Visual Studio 安裝程式。 選取 Azure 開發工作負載,然後選擇 [修改] 以開始安裝工作負載。
在 [ 新增Microsoft Azure 雲端服務 ] 對話框中,選取 [ASP.NET Web 角色 ],然後選取 > 按鈕以將角色新增至專案。 選取 [確定]。
在 [ 新增 ASP.NET Web 應用程式 - WebRole1 ] 對話框中,選取 MVC 範本,然後選取 [ 確定]。
在 方案總管 中,開啟 WebRole1 下的 diagnostics.wadcfgx 檔案。
將檔案的內容取代為下列組態並儲存盤案:
<?xml version="1.0" encoding="utf-8"?> <DiagnosticsConfiguration xmlns="http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration"> <PublicConfig> <WadCfg> <DiagnosticMonitorConfiguration overallQuotaInMB="4096"> <DiagnosticInfrastructureLogs scheduledTransferLogLevelFilter="Error" /> <Logs scheduledTransferPeriod="PT1M" scheduledTransferLogLevelFilter="Error" /> <Directories scheduledTransferPeriod="PT1M"> <IISLogs containerName ="wad-iis-logfiles" /> <FailedRequestLogs containerName ="wad-failedrequestlogs" /> </Directories> <WindowsEventLog scheduledTransferPeriod="PT1M"> <DataSource name="Application!*[System[(Level=1 or Level=2 or Level=3)]]" /> <DataSource name="Windows Azure!*[System[(Level=1 or Level=2 or Level=3 or Level=4)]]" /> </WindowsEventLog> <CrashDumps containerName="wad-crashdumps" dumpType="Mini"> <CrashDumpConfiguration processName="WaIISHost.exe" /> <CrashDumpConfiguration processName="WaWorkerHost.exe" /> <CrashDumpConfiguration processName="w3wp.exe" /> </CrashDumps> <PerformanceCounters scheduledTransferPeriod="PT1M"> <PerformanceCounterConfiguration counterSpecifier="\Memory\Available MBytes" sampleRate="PT3M" /> <PerformanceCounterConfiguration counterSpecifier="\Web Service(_Total)\ISAPI Extension Requests/sec" sampleRate="PT3M" /> <PerformanceCounterConfiguration counterSpecifier="\Web Service(_Total)\Bytes Total/Sec" sampleRate="PT3M" /> <PerformanceCounterConfiguration counterSpecifier="\ASP.NET Applications(__Total__)\Requests/Sec" sampleRate="PT3M" /> <PerformanceCounterConfiguration counterSpecifier="\ASP.NET Applications(__Total__)\Errors Total/Sec" sampleRate="PT3M" /> <PerformanceCounterConfiguration counterSpecifier="\ASP.NET\Requests Queued" sampleRate="PT3M" /> <PerformanceCounterConfiguration counterSpecifier="\ASP.NET\Requests Rejected" sampleRate="PT3M" /> <PerformanceCounterConfiguration counterSpecifier="\Processor(_Total)\% Processor Time" sampleRate="PT3M" /> <PerformanceCounterConfiguration counterSpecifier="\.NET CLR Memory(w3wp)\% Time in GC" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\.NET CLR Exceptions(w3wp)\# of Exceps Thrown / sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\.NET CLR LocksAndThreads(w3wp)\# of current logical Threads" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\.NET CLR LocksAndThreads(w3wp)\# of current physical Threads" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\.NET CLR LocksAndThreads(w3wp)\Current Queue Length" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\.NET CLR LocksAndThreads(w3wp)\Contention Rate / sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\.NET CLR Memory(w3wp)\# Bytes in all Heaps" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\.NET CLR Memory(w3wp)\# GC Handles" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\.NET CLR Memory(w3wp)\# of Pinned Objects" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Connections Connected" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Connections Reconnected" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Connections Disconnected" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Connections Current" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Connection Messages Received Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Connection Messages Sent Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Connection Messages Received/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Connection Messages Sent/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Messages Received Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Messages Received/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Scaleout Message Bus Messages Received/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Messages Published Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Messages Published/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Subscribers Current" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Subscribers Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Subscribers/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Allocated Workers" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Busy Workers" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Topics Current" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Errors: All Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Errors: All/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Errors: Hub Resolution Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Errors: Hub Resolution/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Errors: Hub Invocation Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Errors: Hub Invocation/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Errors: Tranport Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Errors: Transport/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Scaleout Streams Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Scaleout Streams Open" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Scaleout Streams Buffering" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Scaleout Errors Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Scaleout Errors/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Scaleout Send Queue Length" sampleRate="PT10S" /> </PerformanceCounters> </DiagnosticMonitorConfiguration> </WadCfg> <StorageAccount></StorageAccount> </PublicConfig> <PrivateConfig> <StorageAccount name="" key="" endpoint="" /> </PrivateConfig> <IsEnabled>true</IsEnabled> </DiagnosticsConfiguration>
從 工具>NuGet 套件管理員開啟套件管理員主控台。 輸入下列命令以安裝最新版本的 SignalR 和 SignalR 公用程式套件:
install-package microsoft.aspnet.signalr install-package microsoft.aspnet.signalr.utils
設定應用程式,以在啟動或回收角色實例時,將 SignalR 性能計數器安裝到角色實例中。 在 方案總管 中,以滑鼠右鍵按兩下 WebRole1 專案,然後選取 [新增>資料夾]。 將新資料夾 命名為 Startup。
從項目資料夾>/SignalRPerfCounters/packages/Microsoft.AspNet.SignalR.Utils 複製signalr.exe檔案(以 Microsoft.AspNet.SignalR.Utils <新增)。<您在>上一個步驟中建立之 Startup 資料夾的版本/工具。
在 [方案總管] 中,以滑鼠右鍵按兩下 [啟動] 資料夾,然後選取 [新增>現有專案]。 在出現的對話框中,選取 [signalr.exe ],然後選取 [ 新增]。
以滑鼠右鍵按下您建立的 [啟動 ] 資料夾。 選取 [新增]>[新項目]。 選取 [一般] 節點,選取 [文本檔],然後將新專案命名為SignalRPerfCounterInstall.cmd。 此命令檔案會將 SignalR 性能計數器安裝到 Web 角色中。
當 Visual Studio 建立 SignalRPerfCounterInstall.cmd 檔案時,它會自動在主視窗中開啟。 以下列腳本取代檔案的內容,然後儲存並關閉檔案。 此腳本會 執行signalr.exe,此腳本會將 SignalR 性能計數器新增至角色實例。
SET SignalR_LogDir=%~dp0Log\ MKDIR "%SignalR_LogDir%" cd %~dp0 signalr.exe ipc >> "%SignalR_LogDir%SignalR_Log.txt" 2>&1 net localgroup "Performance Monitor Users" "Network Service" /ADD >> "%SignalR_LogDir%NetworkAdd.txt" 2>&1
選取 方案總管 中的signalr.exe檔案。 在檔案的 [屬性] 中,將 [複製到輸出目錄] 設定為 [永遠複製]。
針對SignalRPerfCounterInstall.cmd檔案重複上一個步驟。
以滑鼠右鍵按兩下SignalRPerfCounterInstall.cmd檔案,然後選取[開啟使用]。 在出現的對話框中,選取 [二進位編輯器] ,然後選取 [ 確定]。
在二進位編輯器中,選取檔案中的任何前置位元組並加以刪除。 儲存並關閉檔案。
開啟 ServiceDefinition.csdef ,並新增啟動工作,以在服務啟動時執行 SignalrPerfCounterInstall.cmd 檔案:
<?xml version="1.0" encoding="utf-8"?> <ServiceDefinition name="SignalRPerfCounters" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2015-04.2.6"> <WebRole name="WebRole1" vmsize="Small"> <Startup> <Task commandLine="Startup\SignalRPerfCounterInstall.cmd" executionContext="elevated" taskType="background" /> </Startup> <Sites> <Site name="Web"> <Bindings> <Binding name="Endpoint1" endpointName="Endpoint1" /> </Bindings> </Site> </Sites> <Endpoints> <InputEndpoint name="Endpoint1" protocol="http" port="80" /> </Endpoints> </WebRole> </ServiceDefinition>
開啟
Views/Shared/_Layout.cshtml
並移除檔案結尾的 jQuery 套件組合腳本。<div class="container body-content"> @RenderBody() <hr /> <footer> <p>© @DateTime.Now.Year - My ASP.NET Application</p> </footer> </div> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") @RenderSection("scripts", required: false) </body> </html>
新增 JavaScript 用戶端,以持續在伺服器上呼叫
increment
方法。 開啟Views/Home/Index.cshtml
,並以下列程式代碼取代內容:@{ ViewBag.Title = "Home Page"; } <script src="~/Scripts/jquery-1.10.2.min.js"></script> <script src="~/Scripts/jquery.signalR-2.2.1.min.js"></script> <script src="~/signalr/hubs" type="text/javascript"></script> <div id="body"> <section class="featured"> <div class="content-wrapper"> <p> Hello World! </p> <div style="font-size:large;"> My Counter: <span id="counter"></span> </div> </div> </section> <section class="content-wrapper main-content clear-fix"></section> </div> <script type="text/javascript"> $(document).ready(function () { var hub = $.connection.myHub; hub.client.sendResult = function (x) { console.log('sendResult(' + x + ')'); $("#counter").text(x); window.setTimeout(function () { hub.server.increment(x); }, 1000); }; $.connection.hub.connected = function () {}; $.connection.hub.disconnected = function () {}; $.connection.hub.stateChanged(function (change) { console.log('new State' + change.newState); if (change.newState === $.signalR.connectionState.disconnected) { $.connection.hub.start(); } if (change.newState === $.signalR.connectionState.reconnecting) { console.log('Re-connecting'); } else if (change.newState === $.signalR.connectionState.connected) { console.log('The server is online'); } }); $.connection.hub.error(function (error) { console.log('error ' + error); }); $.connection.hub.logging = true; $.connection.hub.reconnected(function () { console.log('Reconnected'); hub.server.increment(0); }); $.connection.hub.start().done(function () { console.log('hub started'); hub.server.increment(0); }); }); </script>
在名為 Hubs 的 WebRole1 專案中建立新資料夾。 以滑鼠右鍵按兩下 方案總管中的 [中樞] 資料夾,然後選取[新增>專案]。 在 [新增專案] 對話框中,選取 [Web>SignalR] 類別,然後選取 SignalR Hub 類別 (v2) 專案範本。 將新中樞 命名為MyHub.cs ,然後選取 [ 新增]。
MyHub.cs會自動在主視窗中開啟。 以下列程式代碼取代內容,然後儲存並關閉檔案:
using System.Threading.Tasks; using Microsoft.AspNet.SignalR; namespace WebRole1.Hubs { public class MyHub : Hub { public async Task Increment(int x) { await this.Clients.Caller.sendResult(x + 1); } } }
Crank.exe是 SignalR 程式代碼基底所提供的連線密度測試工具。 由於 Crank 需要持續連線,因此您會將一個新增至月臺,以供測試時使用。 將新資料夾新增至名為PersistentConnections的WebRole1專案。 以滑鼠右鍵按下此資料夾,然後選取 [新增>類別]。 將新的類別檔案 命名為MyPersistentConnections.cs ,然後選取 [ 新增]。
Visual Studio 會在主視窗中開啟 MyPersistentConnections.cs 檔案。 以下列程式代碼取代內容,然後儲存並關閉檔案:
using System.Threading.Tasks; using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Infrastructure; namespace WebRole1.PersistentConnections { public class MyPersistentConnection : PersistentConnection { protected override Task OnReceived(IRequest request, string connectionId, string data) { //Return data to calling user return Connection.Send(connectionId, data); } } }
使用 類別
Startup
,SignalR 物件會在 OWIN 啟動時啟動。 開啟或建立 Startup.cs ,並以下列程式代碼取代內容:using Microsoft.Owin; using Owin; using WebRole1.PersistentConnections; // Marks this class for automatic OWIN startup [assembly: OwinStartup(typeof(WebRole1.Startup))] namespace WebRole1 { public partial class Startup { public void Configuration(IAppBuilder app) { ConfigureAuth(app); // Only needed if "No Authentication" was not selected for the project app.MapSignalR(); app.MapSignalR<MyPersistentConnection>("/echo"); } } }
在上述程式代碼中,屬性會將
OwinStartup
這個類別標示為啟動 OWIN。 方法會Configuration
啟動 SignalR。按 F5 在 Microsoft Azure 模擬器 中測試您的應用程式。
注意
如果您在 MapSignalR 遇到 FileLoadException,請將 web.config 中的系結重新導向變更為下列內容:
<dependentAssembly> <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-2.0.2.0" newVersion="2.0.0.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-2.0.2.0" newVersion="2.0.0.0" /> </dependentAssembly>
等候大約一分鐘。 在 Visual Studio 中開啟 Cloud Explorer 工具視窗(檢視>Cloud Explorer),然後展開路徑 。
(Local)/Storage Accounts/(Development)/Tables
按兩下 WADPerformanceCountersTable。 您應該會在資料表數據中看到 SignalR 計數器。 如果您沒有看到數據表,您可能需要重新輸入 Azure 儲存體 認證。 您可能需要選取 [重新整理] 按鈕,才能在 Cloud Explorer 中看到數據表,或在開啟的數據表視窗中選取 [重新整理] 按鈕,以查看數據表中的數據。若要在雲端中測試您的應用程式,請更新 ServiceConfiguration.Cloud.cscfg 檔案,並將 設定
Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString
為有效的 Azure 儲存體 帳戶 連接字串。<?xml version="1.0" encoding="utf-8"?> <ServiceConfiguration serviceName="SignalRPerfCounters" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="4" osVersion="*" schemaVersion="2015-04.2.6"> <Role name="WebRole1"> <Instances count="1" /> <ConfigurationSettings> <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="DefaultEndpointsProtocol=https;AccountName=<account-name>;AccountKey=<account-key>" /> </ConfigurationSettings> </Role> </ServiceConfiguration>
將應用程式部署至您的 Azure 訂用帳戶。 如需如何將應用程式部署至 Azure 的詳細資訊,請參閱 如何建立和部署雲端服務。
請等待數分鐘。 在 Cloud Explorer 中,找出您在上面設定的記憶體帳戶,並在其中尋找
WADPerformanceCountersTable
數據表。 您應該會在資料表數據中看到 SignalR 計數器。 如果您沒有看到數據表,您可能需要重新輸入 Azure 儲存體 認證。 您可能需要選取 [重新整理] 按鈕,才能在 Cloud Explorer 中看到數據表,或在開啟的數據表視窗中選取 [重新整理] 按鈕,以查看數據表中的數據。
特別感謝 Martin Richard 在本教學課程中使用的原始內容。