Azure 웹 역할에서 SignalR 성능 카운터 사용

Luke Latham으로

경고

이 설명서는 최신 버전의 SignalR용이 아닙니다. ASP.NET Core SignalR을 살펴보세요.

SignalR 성능 카운터는 Azure 웹 역할에서 앱의 성능을 모니터링하는 데 사용됩니다. 카운터는 Microsoft Azure Diagnostics 캡처됩니다. 독립 실행형 또는 온-프레미스 앱에 사용되는 것과 동일한 도구인 signalr.exe사용하여 Azure에 SignalR 성능 카운터를 설치합니다. Azure 역할은 일시적이므로 시작할 때 SignalR 성능 카운터를 설치하고 등록하도록 앱을 구성합니다.

사전 요구 사항

SignalR 성능 카운터를 노출하는 Azure Web Role 애플리케이션 만들기

  1. Visual Studio를 엽니다.

  2. Visual Studio에서 파일>새로 만들기>프로젝트를 선택합니다.

  3. 새 프로젝트 대화 상자의 왼쪽에서 Visual C#>Cloud 범주를 선택한 다음, Azure Cloud Service 템플릿을 선택합니다. 앱 이름을 SignalRPerfCounters 로 지정하고 확인을 선택합니다.

    새 클라우드 애플리케이션

    참고

    클라우드 템플릿 범주 또는 Azure Cloud Service 템플릿이 표시되지 않으면 Visual Studio 2017용 Azure 개발 워크로드를 설치해야 합니다. 새 프로젝트 대화 상자의 왼쪽 아래에서 Visual Studio 설치 관리자 열기 링크를 선택하여 Visual Studio 설치 관리자 엽니다. Azure 개발 워크로드를 선택한 다음 수정을 선택하여 워크로드 설치를 시작합니다.

    Visual Studio 설치 관리자 Azure 개발 워크로드

  4. 새 Microsoft Azure Cloud Service 대화 상자에서 ASP.NET 웹 역할을 선택하고 단추를 선택하여 > 프로젝트에 역할을 추가합니다. 확인을 선택합니다.

    ASP.NET 웹 역할 추가

  5. 새 ASP.NET 웹 애플리케이션 - WebRole1 대화 상자에서 MVC 템플릿을 선택한 다음 확인을 선택합니다.

    MVC 및 Web API 추가

  6. 솔루션 탐색기WebRole1에서 진단.wadcfgx 파일을 엽니다.

    솔루션 탐색기 진단.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. 시작하거나 재활용할 때 instance 역할에 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 성능 카운터를 웹 역할에 설치합니다.

    SignalR 성능 카운터 설치 일괄 처리 파일 만들기

  13. Visual Studio에서 SignalRPerfCounterInstall.cmd 파일을 만들면 기본 창에서 자동으로 열립니다. 파일의 내용을 다음 스크립트로 바꾼 다음 파일을 저장하고 닫습니다. 이 스크립트는 signalr.exe를 실행하여 SignalR 성능 카운터를 역할 instance 추가합니다.

    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. 파일 끝에서 jQuery 번들 스크립트를 열고 Views/Shared/_Layout.cshtml 제거합니다.

    <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. 서버에서 메서드를 지속적으로 호출하는 increment JavaScript 클라이언트를 추가합니다. 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. Hubs라는 WebRole1 프로젝트에 새 폴더를 만듭니. 솔루션 탐색기 Hubs 폴더를 마우스 오른쪽 단추로 클릭하고새 항목추가>를 선택합니다. 새 항목 추가 대화 상자에서 >SignalR 범주를 선택한 다음 SignalR Hub 클래스(v2) 항목 템플릿을 선택합니다. 새 허브 이름을 MyHub.cs로 지정하고 추가를 선택합니다.

    새 항목 추가 대화 상자에서 Hubs 폴더에 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에는 영구 연결이 필요하므로 테스트할 때 사용할 사이트에 연결을 추가합니다. PersistentConnections라는 WebRole1 프로젝트에 새 폴더를 추가합니다. 이 폴더를 마우스 오른쪽 단추로 클릭하고 클래스 추가> 선택합니다. 새 클래스 파일의 이름을 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 사용하면 OWIN이 시작될 때 SignalR 개체가 시작됩니다. 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");
            }
        }
    }
    

    위의 코드에서 특성은 OWIN을 OwinStartup 시작하도록 이 클래스를 표시합니다. 메서드는 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. 1분 정도 기다립니다. Visual Studio(클라우드 Explorer 보기>)에서클라우드 Explorer 도구 창을 열고 경로를 (Local)/Storage Accounts/(Development)/Tables확장합니다. WADPerformanceCountersTable을 두 번 클릭합니다. 테이블 데이터에 SignalR 카운터가 표시됩니다. 테이블이 표시되지 않으면 Azure Storage 자격 증명을 다시 입력해야 할 수 있습니다. 새로 고침 단추를 선택하여 클라우드 Explorer 테이블을 보거나 테이블 열기 창에서 새로 고침 단추를 선택하여 테이블의 데이터를 확인해야 할 수 있습니다.

    Visual Studio Cloud Explorer WAD 성능 카운터 테이블 선택

    WAD 성능 카운터 테이블에서 수집된 카운터 표시

  28. 클라우드에서 애플리케이션을 테스트하려면 ServiceConfiguration.Cloud.cscfg 파일을 업데이트하고 를 Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString 유효한 Azure Storage 계정 연결 문자열로 설정합니다.

    <?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. 잠시 기다립니다. 클라우드 Explorer 위에서 구성한 스토리지 계정을 찾아 테이블을 찾 WADPerformanceCountersTable 습니다. 테이블 데이터에 SignalR 카운터가 표시됩니다. 테이블이 표시되지 않으면 Azure Storage 자격 증명을 다시 입력해야 할 수 있습니다. 새로 고침 단추를 선택하여 클라우드 Explorer 테이블을 보거나 테이블 열기 창에서 새로 고침 단추를 선택하여 테이블의 데이터를 확인해야 할 수 있습니다.

이 자습서에서 사용된 원본 콘텐츠에 대한 Martin Richard 에게 특별한 감사를 드립니다.