在 Azure Web 角色中使用 SignalR 效能計數器

作者:Luke Latham

警告

本檔不適用於最新版的 SignalR。 看看ASP.NET Core SignalR

SignalR 效能計數器可用來監視 Azure Web 角色中的應用程式效能。 Microsoft Azure 診斷會擷取計數器。 您可以使用 signalr.exe在 Azure 上安裝 SignalR 效能計數器,這是用於獨立或內部部署應用程式的相同工具。 由於 Azure 角色是暫時性的,因此您會設定應用程式,以在啟動時安裝及註冊 SignalR 效能計數器。

必要條件

建立公開 SignalR 效能計數器的 Azure Web 角色應用程式

  1. 開啟 Visual Studio。

  2. 在 Visual Studio 中,選取 [檔案]> [新增]> [專案]。

  3. 在 [新增專案] 對話方塊中,選取左側的Visual C#>Cloud類別,然後選取Azure 雲端服務範本。 將應用程式命名為 SignalRPerfCounters ,然後選取 [ 確定]。

    新的雲端應用程式

    注意

    如果您沒有看到 雲端 範本類別或 Azure 雲端服務 範本,您必須安裝適用于 Visual Studio 2017 的 Azure 開發 工作負載。 選擇 [新增專案] 對話方塊左下方的 [開啟Visual Studio 安裝程式] 連結,以開啟Visual Studio 安裝程式。 選取 Azure 開發 工作負載,然後選擇 [修改 ] 以開始安裝工作負載。

    Visual Studio 安裝程式 中的 Azure 開發工作負載

  4. 在 [ 新增 Microsoft Azure 雲端服務 ] 對話方塊中,選取 [ASP.NET Web 角色 ],然後選取 > 按鈕以將角色新增至專案。 選取 [確定]。

    新增 ASP.NET Web 角色

  5. [新增 ASP.NET Web 應用程式 - WebRole1 ] 對話方塊中,選取 MVC 範本,然後選取 [ 確定]。

    新增 MVC 和 Web API

  6. 方案總管中,開啟WebRole1底下的diagnostics.wadcfgx檔案。

    方案總管 diagnostics.wadcfgx

  7. 以下列組態取代檔案的內容,並儲存檔案:

    <?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>
    
  8. 工具>NuGet 套件管理員開啟套件管理員主控台。 輸入下列命令以安裝最新版本的 SignalR 和 SignalR 公用程式套件:

    install-package microsoft.aspnet.signalr
    install-package microsoft.aspnet.signalr.utils
    
  9. 設定應用程式以在啟動或回收時,將 SignalR 效能計數器安裝到角色實例中。 在方案總管中,以滑鼠右鍵按一下WebRole1專案,然後選取 [新增>資料夾]。 將新資料夾命名為 Startup

    新增開機檔案夾

  10. 從專案資料夾 > /SignalRPerfCounters/packages/Microsoft.AspNet.SignalR.SignalR.Util) < s 新增 (signalr.exe檔案。<您在上一個步驟中建立之啟動資料夾的版本 > /工具。

  11. 方案總管中,以滑鼠右鍵按一下[啟動] 資料夾,然後選取 [新增>現有專案]。 在出現的對話方塊中,選取 [signalr.exe ],然後選取 [ 新增]。

    將signalr.exe新增至專案

  12. 以滑鼠右鍵按一下您所建立的 [啟動 ] 資料夾。 選取 [新增]>[新項目]。 選取 [ 一般 ] 節點,選取 [文字檔],然後將新專案命名為 SignalRPerfCounterInstall.cmd。 此命令檔案會將 SignalR 效能計數器安裝到 Web 角色中。

    建立 SignalR 效能計數器安裝批次檔

  13. 當 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
    
  14. 方案總管中選取signalr.exe檔案。 在檔案的 [屬性] 中,將 [複製到輸出目錄 ] 設定為 [ 永遠複製]。

    將 [複製到輸出目錄] 設定為 [一律複製]

  15. 針對 SignalRPerfCounterInstall.cmd 檔案重複上一個步驟。

  16. 以滑鼠右鍵按一下 SignalRPerfCounterInstall.cmd 檔案,然後選取 [ 開啟使用]。 在出現的對話方塊中,選取 [ 二進位編輯器 ],然後選取 [ 確定]。

    使用二進位編輯器開啟

  17. 在二進位編輯器中,選取檔案中的任何前置位元組並加以刪除。 儲存並關閉檔案。

    刪除前置位元組

  18. 開啟 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>
    
  19. 開啟 Views/Shared/_Layout.cshtml 並移除檔案結尾的 jQuery 套件組合腳本。

    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
        </footer>
    </div>
    
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)
    </body>
    </html>
    
  20. 新增 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>
    
  21. 在名為HubsWebRole1專案中建立新的資料夾。 以滑鼠右鍵按一下方案總管中的[中樞] 資料夾,然後選取 [新增>專案]。 在 [新增專案] 對話方塊中,選取[Web>SignalR] 類別,然後選取 [SignalR 中樞類別] (v2) 專案範本。 將新的中樞命名為 MyHub.cs ,然後選取 [ 新增]。

    將 SignalR Hub 類別新增至 [新增專案] 對話方塊中的 [中樞] 資料夾

  22. 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);
            }
        }
    }
    
  23. Crank.exe 是 SignalR 程式碼基底所提供的連線密度測試控管。 由於 Crank 需要持續性連線,因此您會將一個新增至您的網站,以供測試時使用。 將新的資料夾新增至名為PersistentConnectionsWebRole1專案。 以滑鼠右鍵按一下此資料夾,然後選取 [新增>類別]。 將新的類別檔案命名為 MyPersistentConnections.cs ,然後選取 [ 新增]。

  24. 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);        
            }
        }
    }
    
  25. 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。

  26. 按下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>
    
  27. 等候大約一分鐘。 在 Visual Studio 中開啟 Cloud Explorer 工具視窗, (檢視>Cloud Explorer) 並展開路徑 (Local)/Storage Accounts/(Development)/Tables 。 按兩下 [WADPerformanceCountersTable]。 您應該會在資料表資料中看到 SignalR 計數器。 如果您沒有看到資料表,您可能需要重新輸入 Azure 儲存體認證。 您可能需要選取 [ 重新整理 ] 按鈕,才能在 Cloud Explorer 中看到資料表,或選取開啟資料表視窗中的 [ 重新 整理] 按鈕,以查看資料表中的資料。

    在 Visual Studio Cloud Explorer 中選取 WAD 效能計數器資料表

    顯示 WAD 效能計數器資料表中收集的計數器

  28. 若要在雲端中測試您的應用程式,請更新 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=&lt;account-name&gt;;AccountKey=&lt;account-key&gt;" />
        </ConfigurationSettings>
      </Role>
    </ServiceConfiguration>
    
  29. 將應用程式部署至您的 Azure 訂用帳戶。 如需如何將應用程式部署至 Azure 的詳細資訊,請參閱 如何建立和部署雲端服務

  30. 請等待數分鐘。 在 [雲端總管] 中,找出您在上面設定的儲存體帳戶,並在其中尋找 WADPerformanceCountersTable 資料表。 您應該會在資料表資料中看到 SignalR 計數器。 如果您沒有看到資料表,您可能需要重新輸入 Azure 儲存體認證。 您可能需要選取 [ 重新 整理] 按鈕,才能在 Cloud Explorer 中查看資料表,或選取開啟資料表視窗中的 [ 重新 整理] 按鈕,以查看資料表中的資料。

特別感謝 Martin Martin 對於本教學課程中使用的原始內容。