Usando contadores de desempenho do SignalR em uma função Web do Azure
Por Luke Latham
Aviso
Esta documentação não é para a versão mais recente do SignalR. Dê uma olhada no ASP.NET Core SignalR.
Os contadores de desempenho do SignalR são usados para monitorar o desempenho do aplicativo em uma função Web do Azure. Os contadores são capturados pelo Diagnóstico do Microsoft Azure. Você instala contadores de desempenho do SignalR no Azure com o signalr.exe, a mesma ferramenta usada para aplicativos autônomos ou locais. Como as funções do Azure são transitórias, você configura um aplicativo para instalar e registrar contadores de desempenho do SignalR na inicialização.
Pré-requisitos
- Visual Studio 2015 ou 2017
- SDK do Microsoft Azure para Visual Studio Observação: reinicie o computador depois de instalar o SDK.
- Assinatura do Microsoft Azure: para se inscrever em uma conta de avaliação gratuita do Azure, consulte Avaliação gratuita do Azure.
Criando um aplicativo de função Web do Azure que expõe contadores de desempenho do SignalR
Abra o Visual Studio.
No Visual Studio, selecione Arquivo>Novo>Projeto.
Na caixa de diálogo Novo Projeto, selecione a categoria Visual C#>Cloud à esquerda e, em seguida, selecione o modelo Serviço de Nuvem do Azure. Nomeie o aplicativo SignalRPerfCounters e selecione OK.
Observação
Se você não vir a categoria de modelo de nuvem ou o modelo de Serviço de Nuvem do Azure, precisará instalar a carga de trabalho de desenvolvimento do Azure para o Visual Studio 2017. Escolha o link Abrir Instalador do Visual Studio no canto inferior esquerdo da caixa de diálogo Novo Projeto para abrir o Instalador do Visual Studio. Selecione a carga de trabalho de desenvolvimento do Azure e, em seguida, escolha Modificar para iniciar a instalação da carga de trabalho.
Na caixa de diálogo Novo Serviço de Nuvem do Microsoft Azure, selecione ASP.NET Função Web e selecione o > botão para adicionar a função ao projeto. Selecione OK.
Na caixa de diálogo Novo Aplicativo Web ASP.NET – WebRole1, selecione o modelo MVC e, em seguida, selecione OK.
No Gerenciador de Soluções, abra o arquivo diagnostics.wadcfgx em WebRole1.
Substitua o conteúdo do arquivo pela seguinte configuração e salve o arquivo:
<?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>
Abra o Console do Gerenciador de Pacotes do Gerenciador de Pacotes NuGet de Ferramentas>. Insira os seguintes comandos para instalar a versão mais recente do SignalR e o pacote de utilitários do SignalR:
install-package microsoft.aspnet.signalr install-package microsoft.aspnet.signalr.utils
Configure o aplicativo para instalar os contadores de desempenho do SignalR na instância de função quando ele for iniciado ou reciclado. No Gerenciador de Soluções, clique com o botão direito do mouse no projeto WebRole1 e selecione Adicionar>Nova Pasta. Nomeie a nova pasta Inicialização.
Copie o arquivo signalr.exe (adicionado com o pacote Microsoft.AspNet.SignalR.Utils) da pasta> do <projeto/SignalRPerfCounters/packages/Microsoft.AspNet.SignalR.Utils.<version>/tools para a pasta de inicialização que você criou na etapa anterior.
No Gerenciador de Soluções, clique com o botão direito do mouse na pasta Inicialização e selecione Adicionar>Item Existente. Na caixa de diálogo exibida, selecione signalr.exe e selecione Adicionar.
Clique com o botão direito do mouse na pasta de inicialização que você criou. Selecione Adicionar>Novo Item. Selecione o nó Geral , selecione Arquivo de Texto e nomeie o novo item SignalRPerfCounterInstall.cmd. Esse arquivo de comando instalará os contadores de desempenho do SignalR na função Web.
Quando o Visual Studio cria o arquivo SignalRPerfCounterInstall.cmd , ele é aberto automaticamente na janela principal. Substitua o conteúdo do arquivo pelo script a seguir e, em seguida, salve e feche o arquivo. Esse script executa signalr.exe, que adiciona os contadores de desempenho do SignalR à instância de função.
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
Selecione o arquivo signalr.exe no Gerenciador de Soluções. Nas Propriedades do arquivo, defina Copiar para o diretório de saída como Copiar sempre.
Repita a etapa anterior para o arquivo SignalRPerfCounterInstall.cmd .
Clique com o botão direito do mouse no arquivo SignalRPerfCounterInstall.cmd e selecione Abrir com. Na caixa de diálogo exibida, selecione Editor binário e selecione OK.
No editor binário, selecione os bytes iniciais no arquivo e exclua-os. Salve e feche o arquivo.
Abra ServiceDefinition.csdef e adicione uma tarefa de inicialização que executa o arquivo SignalrPerfCounterInstall.cmd quando o serviço é iniciado:
<?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>
Abra
Views/Shared/_Layout.cshtml
e remova o script do pacote jQuery do final do arquivo.<div class="container body-content"> @RenderBody() <hr /> <footer> <p>© @DateTime.Now.Year - My ASP.NET Application</p> </footer> </div> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") @RenderSection("scripts", required: false) </body> </html>
Adicione um cliente JavaScript que chame continuamente o
increment
método no servidor. AbraViews/Home/Index.cshtml
e substitua o conteúdo pelo seguinte código:@{ 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>
Crie uma nova pasta no projeto WebRole1 chamada Hubs. Clique com o botão direito do mouse na pasta Hubs no Gerenciador de Soluções e selecione Adicionar>Novo Item. Na caixa de diálogo Adicionar Novo Item, selecione a categoria Web>SignalR e, em seguida, selecione o modelo de item Classe de Hub do SignalR (v2). Nomeie o novo hub MyHub.cs e selecione Adicionar.
MyHub.cs será aberto automaticamente na janela principal. Substitua o conteúdo pelo seguinte código e, em seguida, salve e feche o arquivo:
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); } } }
Crank.exe é uma ferramenta de teste de densidade de conexão fornecida com a base de código do SignalR. Como o Crank requer uma conexão persistente, você adiciona uma ao seu site para uso durante o teste. Adicione uma nova pasta ao projeto WebRole1 chamada PersistentConnections. Clique com o botão direito do mouse nesta pasta e selecione Adicionar>classe. Nomeie o novo arquivo de classe MyPersistentConnections.cs e selecione Adicionar.
O Visual Studio abrirá o arquivo MyPersistentConnections.cs na janela principal. Substitua o conteúdo pelo seguinte código e, em seguida, salve e feche o arquivo:
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); } } }
Usando a classe, os objetos SignalR são iniciados quando o
Startup
OWIN é iniciado. Abra ou crie Startup.cs e substitua o conteúdo pelo seguinte código: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"); } } }
No código acima, o
OwinStartup
atributo marca essa classe para iniciar o OWIN. OConfiguration
método inicia o SignalR.Teste seu aplicativo no Emulador do Microsoft Azure pressionando F5.
Observação
Se você encontrar um FileLoadException no MapSignalR, altere os redirecionamentos de associação em web.config para o seguinte:
<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>
Aguarde cerca de um minuto. Abra a janela de ferramentas do Cloud Explorer no Visual Studio (Exibir>Cloud Explorer) e expanda o caminho .
(Local)/Storage Accounts/(Development)/Tables
Clique duas vezes em WADPerformanceCountersTable. Você deve ver contadores do SignalR nos dados da tabela. Se você não vir a tabela, talvez seja necessário inserir novamente suas credenciais de Armazenamento do Azure. Talvez seja necessário selecionar o botão Atualizar para ver a tabela no Cloud Explorer ou selecionar o botão Atualizar na janela da tabela aberta para ver os dados na tabela.Para testar seu aplicativo na nuvem, atualize o arquivo ServiceConfiguration.Cloud.cscfg e defina como uma cadeia de conexão válida da conta de Armazenamento do
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=<account-name>;AccountKey=<account-key>" /> </ConfigurationSettings> </Role> </ServiceConfiguration>
Implante o aplicativo em sua assinatura do Azure. Para obter detalhes sobre como implantar um aplicativo no Azure, consulte Como criar e implantar um serviço de nuvem.
Aguarde alguns minutos. No Cloud Explorer, localize a conta de armazenamento configurada acima e localize a
WADPerformanceCountersTable
tabela nela. Você deve ver contadores do SignalR nos dados da tabela. Se você não vir a tabela, talvez seja necessário inserir novamente suas credenciais de Armazenamento do Azure. Talvez seja necessário selecionar o botão Atualizar para ver a tabela no Cloud Explorer ou selecionar o botão Atualizar na janela da tabela aberta para ver os dados na tabela.
Agradecimentos especiais a Martin Richard pelo conteúdo original usado neste tutorial.