Поделиться через


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

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

Предупреждение

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

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

Необходимые компоненты

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

  1. Откройте Visual Studio.

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

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

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

    Примечание.

    Если вы не видите категорию шаблона облака или шаблон облачной службы Azure, необходимо установить рабочую нагрузку разработки Azure для Visual Studio 2017. Щелкните ссылку Open 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. В Обозреватель решений откройте файл диагностика.wadcfgx в файле WebRole1.

    Обозреватель решений диагностика.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) из <папки> проекта/SignalRPerfCounters/packages/Microsoft.AspNet.SignalR.Utils.<версия> или инструменты в папку запуска, созданную на предыдущем шаге.

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

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

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

    Создание пакетного файла счетчика производительности 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 в Обозреватель решений. В свойствах файла задайте для копирования в выходной каталог значение Always.

    Настройка копирования в выходной каталог для копирования always

  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. Создайте новую папку в проекте WebRole1 с именем Hubs. Щелкните правой кнопкой мыши папку "Центры" в Обозреватель решений и выберите "Добавить>новый элемент". В диалоговом окне "Добавление нового элемента" выберите категорию Web>SignalR и выберите шаблон элемента класса SignalR (версии 2). Назовите новый концентратор 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 требует постоянного подключения, вы добавляете его на сайт для использования при тестировании. Добавьте новую папку в проект WebRole1 с именем PersistentConnections. Щелкните эту папку правой кнопкой мыши и выберите "Добавить>класс". Назовите новый файл класса 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.

    Примечание.

    Если вы столкнулись с FileLoadException в MapSignalR, измените перенаправления привязки в 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 (просмотр>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 или кнопку "Обновить" в окне открытой таблицы, чтобы просмотреть данные в таблице.

Особое спасибо Мартину Ричарду за исходное содержимое, используемое в этом руководстве.