共用方式為


在 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.Utils 複製signalr.exe檔案(以 Microsoft.AspNet.SignalR.Utils <新增)。<您在>上一個步驟中建立之 Startup 資料夾的版本/工具。

  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 Hub 類別 (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. 請等待數分鐘。 在 Cloud Explorer 中,找出您在上面設定的記憶體帳戶,並在其中尋找 WADPerformanceCountersTable 數據表。 您應該會在資料表數據中看到 SignalR 計數器。 如果您沒有看到數據表,您可能需要重新輸入 Azure 儲存體 認證。 您可能需要選取 [重新整理] 按鈕,才能在 Cloud Explorer 中看到數據表,或在開啟的數據表視窗中選取 [重新整理] 按鈕,以查看數據表中的數據。

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