Использование счетчиков производительности SignalR в веб-роли Azure

Автор Люк Латэм (Luke Latham)

Warning

Эта документация не относится к последней версии SignalR. Ознакомьтесь с ASP.NET Core SignalR.

Счетчики производительности SignalR используются для мониторинга производительности приложения в веб-роли Azure. Счетчики фиксируются система диагностики Microsoft Azure. Вы устанавливаете счетчики производительности SignalR в Azure, используя signalr.exe, то же средство, которое используется для автономных или локальных приложений. Так как роли Azure являются временными, вы настраиваете приложение для установки и регистрации счетчиков производительности SignalR при запуске.

Предварительные требования

Создание приложения веб-роли Azure, предоставляющего счетчики производительности SignalR

  1. Запустите Visual Studio.

  2. В Visual Studio выберите Файл > Создать > Проект.

  3. В диалоговом окне Новый проект выберите категорию облако Visual C# > Cloud слева, а затем выберите шаблон облачная служба Azure . Присвойте приложению имя сигналрперфкаунтерс и нажмите кнопку ОК.

    Новое облачное приложение

    Note

    Если вы не видите категорию шаблон облака или шаблон облачной службы Azure , необходимо установить рабочую нагрузку разработки Azure для Visual Studio 2017. Щелкните ссылку открыть Visual Studio Installer в нижней левой части диалогового окна Новый проект , чтобы открыть Visual Studio Installer. Выберите рабочую нагрузку Разработка Azure и нажмите кнопку изменить , чтобы начать установку рабочей нагрузки.

    Рабочая нагрузка разработки Azure в Visual Studio Installer

  4. В диалоговом окне создание Microsoft Azure облачной службы выберите веб-роль ASP.NET и нажмите кнопку >, чтобы добавить роль в проект. Щелкните ОК.

    Добавить веб-роль ASP.NET

  5. В диалоговом окне Создание веб-приложения ASP.NET — WebRole1 выберите шаблон MVC и нажмите кнопку ОК.

    Добавление MVC и веб-API

  6. В Обозреватель решенийоткройте файл Diagnostics. Wadcfgx в разделе WebRole1.

    Обозреватель решений 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. Скопируйте файл signalr.exe (добавленный с пакетом Microsoft. AspNet. SignalR. utils ) из <project folder> /сигналрперфкаунтерс/паккажес/Микрософт.АСПнет.сигналр.утилс. <version> /тулс в папку Startup , созданную на предыдущем шаге.

  11. В Обозреватель решенийщелкните правой кнопкой мыши папку Startup и выберите команду добавить > существующий элемент. В появившемся диалоговом окне выберите signalr.exe и нажмите кнопку Добавить.

    Добавление signalr.exe в проект

  12. Щелкните правой кнопкой мыши созданную папку автозагрузки . Выберите Добавить > новый элемент. Выберите узел Общие , выберите текстовый файли назовите новый элемент сигналрперфкаунтеринсталл. cmd. Этот командный файл установит счетчики производительности SignalR в веб-роль.

    Создать пакетный файл установки счетчика производительности SignalR

  13. Когда Visual Studio создаст файл сигналрперфкаунтеринсталл. 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. Повторите предыдущий шаг для файла сигналрперфкаунтеринсталл. cmd .

  16. Щелкните правой кнопкой мыши файл сигналрперфкаунтеринсталл. cmd и выберите команду Открыть с помощью. В появившемся диалоговом окне выберите двоичный редактор и нажмите кнопку ОК.

    Открыть с помощью двоичного редактора

  17. В двоичном редакторе выберите все начальные байты в файле и удалите их. Сохраните файл и закройте его.

    Удалить начальные байты

  18. Откройте ServiceDefinition. csdef и добавьте задачу запуска, которая выполняет файл сигналрперфкаунтеринсталл. 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. Создайте новую папку в проекте WebRole1 с именемHubs. Щелкните правой кнопкой мыши папку концентраторы в Обозреватель решений и выберите команду добавить > новый элемент. В диалоговом окне Добавление нового элемента выберите категорию веб- > SignalR и выберите шаблон элемента класс концентратора SignalR (v2) . Присвойте новому концентратору имя MyHub.CS и выберите Добавить.

    Добавление класса концентратора SignalR в папку "концентраторы" в диалоговом окне "Добавление нового элемента"

  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. Так как для погромче требуется постоянное подключение, вы добавляете его на сайт для использования при тестировании. Добавьте новую папку в проект 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 класса объекты 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. Протестируйте приложение в эмулятор Microsoft Azure, нажав клавишу F5.

    Note

    Если вы столкнулись с 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. Подождите примерно одну минуту. Откройте окно инструментов Cloud Explorer в Visual Studio (View > Cloud Explorer) и разверните путь (Local)/Storage Accounts/(Development)/Tables . Дважды щелкните WADPerformanceCountersTable. Счетчики SignalR должны отображаться в табличных данных. Если таблица не отображается, может потребоваться повторно ввести учетные данные службы хранилища Azure. Может потребоваться нажать кнопку Обновить , чтобы просмотреть таблицу в Cloud Explorer или нажать кнопку Обновить в окне Открытие таблицы, чтобы просмотреть данные в таблице.

    Выбор таблицы счетчиков производительности WAD в Visual Studio Cloud Explorer

    Отображение счетчиков, собранных в таблице счетчиков производительности 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 или нажать кнопку Обновить в окне Открытие таблицы, чтобы просмотреть данные в таблице.

Для первоначального содержимого, используемого в этом учебнике, особое внимание соследуется спасибо.