Desempenho do SignalR

por Patrick Fletcher

Aviso

Esta documentação não é para a versão mais recente do SignalR. Dê uma olhada em ASP.NET Core SignalR.

Este tópico descreve como projetar, medir e melhorar o desempenho em um aplicativo SignalR.

Versões de software usadas neste tópico

Versões anteriores deste tópico

Para obter informações sobre versões anteriores do SignalR, consulte Versões mais antigas do SignalR.

Perguntas e comentários

Deixe comentários sobre como você gostou deste tutorial e o que poderíamos melhorar nos comentários na parte inferior da página. Se você tiver perguntas que não estão diretamente relacionadas ao tutorial, poderá postá-las no fórum do ASP.NET SignalR ou StackOverflow.com.

Para obter uma apresentação recente sobre o desempenho e o dimensionamento do SignalR, consulte Dimensionando a Web em tempo real com ASP.NET SignalR.

Este tópico contém as seguintes seções:

Considerações sobre o design

Esta seção descreve padrões que podem ser implementados durante o design de um aplicativo SignalR, para garantir que o desempenho não esteja sendo prejudicado gerando tráfego de rede desnecessário.

Frequência da mensagem de limitação

Mesmo em um aplicativo que envia mensagens em alta frequência (como um aplicativo de jogos em tempo real), a maioria dos aplicativos não precisa enviar mais do que algumas mensagens por segundo. Para reduzir a quantidade de tráfego gerada por cada cliente, um loop de mensagem pode ser implementado que filas e envia mensagens com não mais frequência do que uma taxa fixa (ou seja, até um determinado número de mensagens serão enviadas a cada segundo, se houver mensagens nesse intervalo de tempo a serem enviadas). Para obter um aplicativo de exemplo que limita as mensagens a uma determinada taxa (do cliente e do servidor), consulte High-Frequency Realtime with SignalR.

Reduzindo o tamanho da mensagem

Você pode reduzir o tamanho de uma mensagem SignalR reduzindo o tamanho dos objetos serializados. No código do servidor, se você estiver enviando um objeto que contém propriedades que não precisam ser transmitidas, impeça que essas propriedades sejam serializadas usando o JsonIgnore atributo . Os nomes das propriedades também são armazenados na mensagem; os nomes das propriedades podem ser reduzidos usando o JsonProperty atributo . O exemplo de código a seguir demonstra como excluir uma propriedade de ser enviada ao cliente e como reduzir nomes de propriedade:

Código do servidor .NET que demonstra o atributo JsonIgnore para excluir dados de serem enviados ao cliente e o atributo JsonProperty para reduzir o tamanho da mensagem

using Newtonsoft.Json; 
using System; 
public class ShapeModel
{
    [JsonProperty("l")]
    public double Left { get; set; }
    [JsonProperty("t")]
    public double Top { get; set; }
    // We don't want the client to get the "LastUpdatedBy" property
    [JsonIgnore]
    public string LastUpdatedBy { get; set; }
}

Para manter a legibilidade/manutenção no código do cliente, os nomes de propriedade abreviados podem ser remapeados para nomes amigáveis para humanos após o recebimento da mensagem. O exemplo de código a seguir demonstra uma possível maneira de remapear nomes reduzidos para os mais longos, definindo um contrato de mensagem (mapeamento) e usando a reMap função para aplicar o contrato à classe de mensagem otimizada:

Código JavaScript do lado do cliente que remapea nomes de propriedade abreviados para nomes legíveis por humanos

function reMap(smallObject, contract) {
    var largeObject = {};
    for (var smallProperty in contract) {
        largeObject[contract[smallProperty]] = smallObject[smallProperty];
    }
    return largeObject;
}
var shapeModelContract = {
    l: "left",
    t: "top"
};
myHub.client.setShape = function (shapeModelSmall) {
    var shapeModel = reMap(shapeModelSmall, shapeModelContract);
    // shapeModelSmall has "l" and "t" properties  but after remapping
    // shapeModel now has "left" and "top" properties
};

Os nomes também podem ser reduzidos em mensagens do cliente para o servidor, usando o mesmo método.

Reduzir o volume de memória (ou seja, a quantidade de memória usada para a mensagem) do objeto de mensagem também pode melhorar o desempenho. Por exemplo, se o intervalo completo de um int não for necessário, um short ou byte poderá ser usado.

Como as mensagens são armazenadas no barramento de mensagens na memória do servidor, reduzir o tamanho das mensagens também pode resolver problemas de memória do servidor.

Ajustando seu servidor SignalR para desempenho

As configurações a seguir podem ser usadas para ajustar seu servidor para melhorar o desempenho em um aplicativo SignalR. Para obter informações gerais sobre como melhorar o desempenho em um aplicativo ASP.NET, consulte Aprimorando ASP.NET desempenho.

Configurações do SignalR

  • DefaultMessageBufferSize: por padrão, o SignalR retém 1000 mensagens na memória por hub por conexão. Se mensagens grandes estiverem sendo usadas, isso poderá criar problemas de memória que podem ser atenuados reduzindo esse valor. Essa configuração pode ser definida no Application_Start manipulador de eventos em um aplicativo ASP.NET ou no Configuration método de uma classe de inicialização OWIN em um aplicativo auto-hospedado. O exemplo a seguir demonstra como reduzir esse valor para reduzir o volume de memória do aplicativo, a fim de reduzir a quantidade de memória do servidor usada:

    Código do servidor .NET em Startup.cs para diminuir o tamanho do buffer de mensagem padrão

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // Any connection or hub wire up and configuration should go here
            GlobalHost.Configuration.DefaultMessageBufferSize = 500;
            app.MapSignalR();
        }
    }
    

Configurações do IIS

  • Máximo de solicitações simultâneas por aplicativo: aumentar o número de solicitações simultâneas do IIS aumentará os recursos do servidor disponíveis para atender às solicitações. O valor padrão é 5000; para aumentar essa configuração, execute os seguintes comandos em um prompt de comando com privilégios elevados:

    cd %windir%\System32\inetsrv\
    appcmd.exe set config /section:system.webserver/serverRuntime 
            /appConcurrentRequestLimit:10000
    
  • ApplicationPool QueueLength: esse é o número máximo de solicitações que Http.sys filas para o pool de aplicativos. Quando a fila estiver cheia, novas solicitações receberão uma resposta 503 "Serviço Indisponível". O valor padrão é 1000.

    Reduzir o comprimento da fila para o processo de trabalho no pool de aplicativos que hospeda seu aplicativo conservará os recursos de memória. Para obter mais informações, consulte Gerenciamento, ajuste e configuração de pools de aplicativos.

ASP.NET configuração

Esta seção inclui as configurações que podem ser definidas no aspnet.config arquivo. Esse arquivo é encontrado em um dos dois locais, dependendo da plataforma:

  • %windir%\Microsoft.NET\Framework\v4.0.30319\aspnet.config
  • %windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet.config

ASP.NET configurações que podem melhorar o desempenho do SignalR incluem o seguinte:

  • Máximo de solicitações simultâneas por CPU: aumentar essa configuração pode aliviar gargalos de desempenho. Para aumentar essa configuração, adicione a seguinte configuração ao aspnet.config arquivo:

    <?xml version="1.0" encoding="UTF-8" ?>
    <configuration>
        <system.web>
            <applicationPool maxConcurrentRequestsPerCPU="20000" />
        </system.web>
    </configuration>
    
  • Limite de Fila de Solicitação: quando o número total de conexões exceder a maxConcurrentRequestsPerCPU configuração, ASP.NET iniciará a limitação de solicitações usando uma fila. Para aumentar o tamanho da fila, você pode aumentar a requestQueueLimit configuração. Para fazer isso, adicione a seguinte configuração ao processModel nó no (em config/machine.config vez de aspnet.config):

    <processModel autoConfig="false" requestQueueLimit="250000" />
    

Solucionando problemas de desempenho

Esta seção descreve maneiras de encontrar gargalos de desempenho em seu aplicativo.

Verificando se o WebSocket está sendo usado

Embora o SignalR possa usar uma variedade de transportes para comunicação entre o cliente e o servidor, o WebSocket oferece uma vantagem significativa de desempenho e deve ser usado se o cliente e o servidor dão suporte a ele. Para determinar se o cliente e o servidor atendem aos requisitos do WebSocket, consulte Transportes e fallbacks. Para determinar qual transporte está sendo usado em seu aplicativo, você pode usar as ferramentas de desenvolvedor do navegador e examinar os logs para ver qual transporte está sendo usado para a conexão. Para obter informações sobre como usar as ferramentas de desenvolvimento do navegador na Internet Explorer e no Chrome, consulte Transportes e Fallbacks.

Usando contadores de desempenho do SignalR

Esta seção descreve como habilitar e usar contadores de desempenho do SignalR, encontrados no Microsoft.AspNet.SignalR.Utils pacote.

Instalando signalr.exe

Contadores de desempenho podem ser adicionados ao servidor usando um utilitário chamado SignalR.exe. Para instalar esse utilitário, siga estas etapas:

  1. No Visual Studio, selecione FerramentasGerenciador de Pacotes>> NuGetGerenciar Pacotes NuGet para solução

  2. Pesquise signalr.utils e selecione Instalar.

    Captura de tela que mostra os Utilitários do Microsoft A SP dot NET Signal R selecionados.

  3. Aceite o contrato de licença para instalar o pacote.

  4. SignalR.exe será instalado em <project folder>/packages/Microsoft.AspNet.SignalR.Utils.<version>/tools.

Instalando contadores de desempenho com SignalR.exe

Para instalar contadores de desempenho do SignalR, execute SignalR.exe em um prompt de comando com privilégios elevados com o seguinte parâmetro:

SignalR.exe ipc

Para remover contadores de desempenho do SignalR, execute SignalR.exe em um prompt de comando com privilégios elevados com o seguinte parâmetro:

SignalR.exe upc

Contadores de desempenho do SignalR

O pacote de utilitários instala os seguintes contadores de desempenho. Os contadores "Total" medem o número de eventos desde o último pool de aplicativos ou reinicialização do servidor.

Métricas de conexão

As métricas a seguir medem os eventos de tempo de vida da conexão que ocorrem. Para obter mais informações, consulte Noções básicas e tratamento de eventos de tempo de vida da conexão.

  • Conexões conectadas
  • Conexões Reconectadas
  • Conexões desconectadas
  • Conexões Atuais

Métricas de mensagens

As métricas a seguir medem o tráfego de mensagens gerado pelo SignalR.

  • Total de Mensagens de Conexão Recebidas
  • Total de Mensagens de Conexão Enviadas
  • Mensagens de conexão recebidas/s
  • Mensagens de conexão enviadas/s

Métricas do barramento de mensagens

As métricas a seguir medem o tráfego por meio do barramento de mensagens do SignalR interno, a fila na qual todas as mensagens do SignalR de entrada e saída são colocadas. Uma mensagem é Publicada quando é enviada ou transmitida. Um Assinante neste contexto é uma assinatura no barramento de mensagens; isso deve ser igual ao número de clientes mais o próprio servidor. Um Trabalho Alocado é um componente que envia dados para conexões ativas; um Trabalhador Ocupado é aquele que está enviando ativamente uma mensagem.

  • Total de mensagens recebidas do barramento de mensagens
  • Mensagens recebidas/s do barramento de mensagens
  • Total de Mensagens do Barramento de Mensagens Publicadas
  • Mensagens do Barramento de Mensagens Publicadas/S
  • Assinantes do Barramento de Mensagens Atuais
  • Total de Assinantes do Barramento de Mensagens
  • Assinantes do Barramento de Mensagens/S
  • Trabalhos Alocados do Barramento de Mensagens
  • Trabalhadores ocupados do Barramento de Mensagens
  • Tópicos atuais do Barramento de Mensagens

Métricas de erro

As métricas a seguir medem erros gerados pelo tráfego de mensagens do SignalR. Erros de resolução de hub ocorrem quando um hub ou método de hub não pode ser resolvido. Erros de invocação de hub são exceções geradas ao invocar um método de hub. Erros de transporte são erros de conexão gerados durante uma solicitação OU resposta HTTP.

  • Erros: Todo o Total
  • Erros: Tudo/S
  • Erros: Total de Resolução do Hub
  • Erros: Resolução do Hub/s
  • Erros: Total de Invocação do Hub
  • Erros: Invocação do Hub/S
  • Erros: Total de Transporte
  • Erros: Transporte/s

Métricas de expansão

As métricas a seguir medem o tráfego e os erros gerados pelo provedor de expansão. Um Stream nesse contexto é uma unidade de escala usada pelo provedor de expansão; esta será uma tabela se SQL Server for usado, um Tópico se o Barramento de Serviço for usado e uma Assinatura se o Redis for usado. Cada fluxo garante operações ordenadas de leitura e gravação; um único fluxo é um possível gargalo de escala, portanto, o número de fluxos pode ser aumentado para ajudar a reduzir esse gargalo. Se vários fluxos forem usados, o SignalR distribuirá automaticamente mensagens (fragmentos) entre esses fluxos de uma maneira que garanta que as mensagens enviadas de qualquer conexão determinada estejam em ordem.

A configuração MaxQueueLength controla o comprimento da fila de envio de expansão mantida pelo SignalR. Defini-lo como um valor maior que 0 colocará todas as mensagens em uma fila de envio para serem enviadas uma de cada vez para o backplane de mensagens configurado. Se o tamanho da fila ultrapassar o comprimento configurado, as chamadas subsequentes a serem enviadas falharão imediatamente com invalidOperationException até que o número de mensagens na fila seja menor que a configuração novamente. O enfileiramento é desabilitado por padrão porque os backplanes implementados geralmente têm sua própria fila ou controle de fluxo em vigor. No caso de SQL Server, o pool de conexões limita efetivamente o número de envios acontecendo de uma só vez.

Por padrão, apenas um fluxo é usado para SQL Server e Redis, cinco fluxos são usados para o Barramento de Serviço e a fila está desabilitada, mas essas configurações podem ser alteradas por meio da configuração no SQL Server e no Barramento de Serviço:

Código do servidor .NET para configurar a contagem de tabelas e o comprimento da fila para SQL Server backplane

var connectionString = "(your connection string)";
var config = new SqlScaleoutConfiguration(connectionString) { 
TableCount = 3,
MaxQueueLength = 50 };
GlobalHost.DependencyResolver.UseSqlServer(config);

Código do servidor .NET para configurar a contagem de tópicos e o comprimento da fila para o backplane do Barramento de Serviço

string connectionString = "(your connection string)";
var config = new ServiceBusScaleoutConfiguration(connectionString, "YourAppName") { 
TopicCount = 3,
MaxQueueLength = 50 };
GlobalHost.DependencyResolver.UseServiceBus(config);

Um fluxo de buffer é aquele que inseriu um estado com falha; quando o fluxo estiver no estado com falha, todas as mensagens enviadas para o backplane falharão imediatamente até que o fluxo não esteja mais falhando. O Comprimento da Fila de Envio é o número de mensagens que foram postadas, mas ainda não enviadas.

  • Mensagens do barramento de mensagens de expansão recebidas/s
  • Total de fluxos de expansão
  • Fluxos do Scaleout Abertos
  • Buffer de fluxos de expansão
  • Total de erros de scaleout
  • Erros de scaleout/s
  • Tamanho da Fila de Envio do Scaleout

Para obter mais informações sobre o que esses contadores estão medindo, consulte Scaleout do SignalR com Barramento de Serviço do Azure.

Usando outros contadores de desempenho

Os contadores de desempenho a seguir também podem ser úteis para monitorar o desempenho do aplicativo.

Memória

  • Bytes do .NET CLR Memory\# em todos os Heaps (para w3wp)

ASP.NET

  • ASP.NET\Solicitações Atuais
  • ASP.NET\Enfileirado
  • ASP.NET\Rejeitado

CPU

  • Informações do Processador\Tempo do Processador

TCP/IP

  • TCPv6/Connections Established
  • TCPv4/Conexões Estabelecidas

Serviço Web

  • Serviço Web\Conexões Atuais
  • Serviço Web\Conexões Máximas

Threading

  • Bloqueios e threads clr do .NET\# dos threads lógicos atuais
  • Bloqueios e threads clr do .NET\# dos threads físicos atuais

Outros recursos

Para obter mais informações sobre ASP.NET monitoramento e ajuste de desempenho, consulte os seguintes tópicos: