Guia de solução de problemas comuns do Serviço do Azure SignalR

Este artigo fornece diretrizes de solução de problemas para alguns problemas comuns que os clientes podem encontrar.

Token de acesso muito longo

Possíveis erros

  • Por parte do clienteERR_CONNECTION_
  • 414 URI muito longo
  • 413 Conteúdo Muito Grande
  • O token de acesso não deve ser maior do que 4K. Solicitação 413 entidade muito grande

Causa raiz

Para HTTP/2, o comprimento máximo de um único cabeçalho é 4 K, sendo assim, se usar o navegador para acessar o serviço do Azure, ocorrerá um erro ERR_CONNECTION_ para essa limitação.

Para clientes HTTP/1.1 ou C#, o comprimento máximo do URI é 12 K, o comprimento máximo do cabeçalho é 16 K.

Com o SDK versão 1.0.6 ou superior, /negotiategerará 413 Payload Too Large quando o token de acesso gerado for maior do que 4 K.

Solução

Por padrão, as declarações de context.User.Claims são incluídas ao gerar o token de acesso JWT para ASRS(Azure SignalRService), para que as declarações sejam preservadas e possam ser passadas do ASRS para o Hub quando o cliente se conectar ao Hub.

Em alguns casos, context.User.Claims são usados para armazenar muitas informações para o servidor de aplicativos, e a maioria não é usada por Hubs, mas por outros componentes.

O token de acesso gerado é transmitido pela rede e para conexões WebSocket/SSE, os tokens de acesso são passados por meio de cadeias de caracteres de consulta. Como prática recomendada, sugerimos passar somente as declarações necessárias do cliente por meio do ASRS para seu servidor de aplicativos quando o Hub precisar.

Existe um ClaimsProvider para você personalizar as declarações passando pelo ASRS dentro do token de acesso.

Para ASP.NET Core:

services.AddSignalR()
        .AddAzureSignalR(options =>
            {
                // pick up necessary claims
                options.ClaimsProvider = context => context.User.Claims.Where(...);
            });

Para ASP.NET:

services.MapAzureSignalR(GetType().FullName, options =>
            {
                // pick up necessary claims
                options.ClaimsProvider = context.Authentication?.User.Claims.Where(...);
            });

Está com problemas ou tem comentários sobre a solução de problemas? Fale conosco.

Necessário TLS 1.2

Possíveis erros

  • Erro #279 “Nenhum servidor disponível” do ASP.NET
  • Erro #324 "A conexão não está ativa, os dados não podem ser enviados para o serviço." do ASP.NET
  • "Ocorreu um erro ao fazer a solicitação HTTP para https://<API endpoint>. Isso pode ser devido ao fato de que o certificado do servidor não está configurado corretamente com HTTP.SYS no caso do HTTPS. Este erro também pode ser causado por uma incompatibilidade da associação de segurança entre o cliente e o servidor. "

Causa raiz

O Serviço do Azure suporta apenas a TLS 1.2 para questões de segurança. Com o .NET Framework, é possível que o TLS 1.2 não seja o protocolo padrão. Como resultado, as conexões do servidor com o ASRS não podem ser estabelecidas com êxito.

Guia de Solução de Problemas

  1. Se esse erro puder ser reproduzido localmente, desmarque o Apenas Meu Código e lance todas as exceções CLR e depure o servidor de aplicativos localmente para ver qual exceção é lançada.

    • Desmarque Apenas Meu Código

      Uncheck Just My Code

    • Lance as exceções CLR

      Throw CLR exceptions

    • Consulte as exceções lançadas ao depurar o código do lado do servidor do aplicativo:

      Exception throws

  2. Para ASP.NET, você também pode adicionar o código a seguir ao seu Startup.cs para habilitar o rastreamento detalhado e ver os erros do log.

    app.MapAzureSignalR(this.GetType().FullName);
    // Make sure this switch is called after MapAzureSignalR
    GlobalHost.TraceManager.Switch.Level = SourceLevels.Information;
    

Solução

Adicione o seguinte código à sua Inicialização:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Está com problemas ou tem comentários sobre a solução de problemas? Fale conosco.

400 Solicitação incorreta retornado para solicitações de cliente

Causa raiz

Verifique se a solicitação do cliente tem várias cadeias de caracteres de consulta hub. hub é um parâmetro de consulta preservado e será lançado 400 se o serviço detectar mais de um hub na consulta.

Está com problemas ou tem comentários sobre a solução de problemas? Fale conosco.

401 não autorizado retornado para solicitações de cliente

Causa raiz

Atualmente, o valor padrão do tempo de vida do token JWT é de 1 (uma) hora.

Para o ASP.NET Core SignalR, não há problema quando ele está usando o tipo de transporte WebSocket.

Para outro tipo de transporte do ASP.NET Core SignalR, SSE e sondagem longa, o tempo de vida padrão significa, por padrão, que a conexão pode persistir por no máximo uma hora.

Para o ASP.NET SignalR, o cliente envia uma solicitação "keep alive" /ping ao serviço de tempos em tempos, quando a /ping falha, o cliente anula a conexão e nunca se reconecta. Para o ASP.NET SignalR, o tempo de vida do token padrão faz com que a conexão dure no máximo uma hora para todos os tipos de transporte.

Solução

Para questões de segurança, o TTL estendido não é recomendado. Sugerimos adicionar lógica de reconexão do cliente para reiniciar a conexão quando um 401 ocorre. Quando o cliente reinicia a conexão, ele negocia com o servidor de aplicativos para obter o token JWT novamente e recebe um token renovado.

Confira aqui para saber como reiniciar as conexões de cliente.

Está com problemas ou tem comentários sobre a solução de problemas? Fale conosco.

404 retornado para solicitações de cliente

Para uma conexão persistente do SignalR, primeiro ele faz /negotiate para o serviço do Azure SignalR e depois estabelece a conexão verdadeira com o serviço do Azure SignalR.

Guia de Solução de Problemas

  • Seguindo Como visualizar as solicitações de saída para obter a solicitação do cliente para o serviço.
  • Verifique o URL da solicitação quando 404 ocorrer. Se o URL estiver direcionando para seu aplicativo Web e, de forma similar, para {your_web_app}/hubs/{hubName}, verifique se o cliente SkipNegotiation é true. O cliente recebe uma URL de redirecionamento quando negocia pela primeira vez com o servidor de aplicativos. O cliente não pode ignorar a negociação ao usar o Azure SignalR.
  • Outro 404 pode acontecer quando a solicitação de conexão é tratada mais de 5 (cinco) segundos após /negotiate ser chamada. Verifique o carimbo de data/hora da solicitação do cliente e registre um incidente em nosso site se a solicitação para o serviço tiver uma resposta lenta.

Está com problemas ou tem comentários sobre a solução de problemas? Fale conosco.

Retorno 404 de uma solicitação de reconexão para o ASP.NET SignalR

Para o ASP.NET SignalR, quando a conexão do cliente cai, ela se reconecta usando o mesmo connectionId por três vezes antes de parar a conexão. /reconnect pode ajudar se a conexão cair devido a problemas intermitentes de rede que /reconnect pode restabelecer a conexão persistente com êxito. Em outras circunstâncias, por exemplo, a conexão do cliente cai devido à queda da conexão do servidor roteado, ou o Serviço do SignalR está com algum erro interno como reinicialização/failover/implantação da instância, conexão não existe mais, portanto /reconnect retorna 404. É o comportamento esperado para /reconnect e, depois de três vezes, a conexão é interrompida. Sugerimos lógica de reinicialização de conexão quando a conexão é interrompida.

Está com problemas ou tem comentários sobre a solução de problemas? Fale conosco.

Erro 429 (Excesso de Solicitações) retornado para solicitações de cliente

Existem dois casos.

A contagem de conexões simultâneas excede o limite

Para instâncias Gratuitas, o limite de contagem de conexões Simultâneas é de 20. Para instâncias Standard, o limite de contagem de conexões Simultâneaspor unidade é 1 K, o que significa que o 100 unidades permitem conexões simultâneas de 100-K.

As conexões incluem conexões de cliente e de servidor. Verifique aqui como as conexões são contadas.

Muitas solicitações negociando ao mesmo tempo

Sugerimos atraso aleatório antes da reconexão. Confira aqui os exemplos de como fazer novas tentativas.

Está com problemas ou tem comentários sobre a solução de problemas? Fale conosco.

Erro 500 ao negociar: o Serviço do Azure SignalR ainda não está conectado. tente novamente mais tarde

Causa raiz

Esse erro é relatado quando não há nenhuma conexão de servidor conectada com o Serviço do Azure SignalR.

Guia de Solução de Problemas

Habilite o rastreamento do lado do servidor para descobrir os detalhes do erro quando o servidor tenta se conectar ao Serviço do Azure SignalR.

Habilitar o registro em log do lado do servidor para o ASP.NET Core SignalR

O registro em log do lado do servidor para ASP.NET Core SignalR se integra com o ILoggerregistro em log com base, fornecido pelo ASP.NET Core Framework. Habilite o registro em log do lado do servidor usando ConfigureLogging, um exemplo de uso da seguinte maneira:

.ConfigureLogging((hostingContext, logging) =>
        {
            logging.AddConsole();
            logging.AddDebug();
        })

As categorias de agente para o Azure SignalR sempre começam com Microsoft.Azure.SignalR. Para habilitar logs detalhados do Azure SignalR, configure os prefixos anteriores para o nível Debug no arquivo appsettings.jsno conforme abaixo:

{
    "Logging": {
        "LogLevel": {
            ...
            "Microsoft.Azure.SignalR": "Debug",
            ...
        }
    }
}

Habilitar rastreamentos no lado do servidor para o ASP.NET SignalR

Ao usar o SDK versão >= 1.0.0, você pode habilitar os rastreamentos adicionando o seguinte a web.config: (Detalhes)

<system.diagnostics>
    <sources>
      <source name="Microsoft.Azure.SignalR" switchName="SignalRSwitch">
        <listeners>
          <add name="ASRS" />
        </listeners>
      </source>
    </sources>
    <!-- Sets the trace verbosity level -->
    <switches>
      <add name="SignalRSwitch" value="Information" />
    </switches>
    <!-- Specifies the trace writer for output -->
    <sharedListeners>
      <add name="ASRS" type="System.Diagnostics.TextWriterTraceListener" initializeData="asrs.log.txt" />
    </sharedListeners>
    <trace autoflush="true" />
  </system.diagnostics>

Está com problemas ou tem comentários sobre a solução de problemas? Fale conosco.

Tipos de conexão de cliente

Quando o cliente está conectado ao Azure SignalR, a conexão persistente entre o cliente e o Azure SignalR pode cair às vezes por diferentes motivos. Esta seção descreve as várias causas da queda da conexão, e fornece algumas diretrizes sobre como identificar a causa raiz.

Possíveis erros no lado do cliente

  • The remote party closed the WebSocket connection without completing the close handshake
  • Service timeout. 30000.00ms elapsed without receiving a message from service.
  • {"type":7,"error":"Connection closed with an error."}
  • {"type":7,"error":"Internal server error."}

Causa raiz

As conexões de cliente podem cair em várias circunstâncias:

  • Quando Hub gera exceções com a solicitação de entrada
  • Quando a conexão do servidor para o qual o cliente foi encaminhado cai; consulte a seção abaixo para obter detalhes sobre quedas de conexão do servidor
  • Quando ocorre um problema de conectividade de rede entre o cliente e o Serviço do SignalR
  • Quando o Serviço do SignalR tem algum erro interno, como reinicialização de instância, failover, implantação e assim por diante

Guia de Solução de Problemas

  1. Abra o log do servidor de aplicativo para verificar se algo anormal ocorreu
  2. Verifique o log de eventos do servidor do aplicativo para ver se o servidor de aplicativos foi reiniciado
  3. Abra um incidente em nosso site para fornecer o período de tempo e nos envie por email o nome do recurso

Está com problemas ou tem comentários sobre a solução de problemas? Fale conosco.

As conexões do cliente aumentam constantemente

A causado pode ser o uso impróprio da conexão do cliente. Se alguém esquecer de parar/descartar o SignalR do cliente, a conexão permanecerá aberta.

Possíveis erros vistos a partir das métricas do SignalR que estão na seção Monitoramento do menu de recursos do portal do Azure

As conexões de cliente aumentam constantemente por um longo período nas métricas do Azure SignalR.

Client connection increasing constantly

Causa raiz

A conexão SignalR do cliente DisposeAsync nunca é chamada, a conexão permanece aberta.

Guia de Solução de Problemas

Verifique se o SignalR do cliente nunca fecha.

Solução

Verifique se você fechou a conexão. Chame manualmente HubConnection.DisposeAsync() para parar a conexão depois de usá-la.

Por exemplo:

var connection = new HubConnectionBuilder()
	.WithUrl(...)
	.Build();
try
{
	await connection.StartAsync();
	// Do your stuff
	await connection.StopAsync();
}
finally
{
	await connection.DisposeAsync();
}

Uso impróprio conexão do cliente

Exemplo do Azure Function

Esse problema geralmente ocorre quando alguém estabelece uma conexão do SignalR em um método do Azure Function em vez de torná-la um membro estático da classe da função. Você pode esperar que apenas uma conexão de cliente seja estabelecida, mas vê o número de conexões do cliente aumentar constantemente nas métricas. Todas essas conexões são descartadas somente após a reinicialização do serviço do Azure Function ou do Azure SignalR. Esse comportamento ocorre porque, para cada solicitação, o Azure Function cria uma conexão de cliente e, se você não parar a conexão do cliente no método da função, o cliente manterá as conexões ativas para o serviço do Azure SignalR.

Solução

Está com problemas ou tem comentários sobre a solução de problemas? Fale conosco.

Quedas de conexão do servidor

Quando o servidor de aplicativos é iniciado, em segundo plano, o SDK do Azure começa a iniciar as conexões do servidor com o Azure SignalR remoto. Conforme descrito em Funcionamento interno do Serviço do Azure SignalR, o Azure SignalR encaminha os tráfegos de entrada do cliente para essas conexões de servidor. Depois que uma conexão de servidor cai, todas as conexões do cliente que ele serve também são fechadas.

Como as conexões entre o servidor de aplicativos e o Serviço do SignalR são conexões persistentes, elas podem enfrentar problemas de conectividade de rede. No SDK do Servidor, temos uma estratégia de Sempre reconectar as conexões do servidor. Como melhor prática, também incentivamos os usuários a adicionar lógica de reconexão contínua aos clientes com um tempo de atraso aleatório para evitar solicitações simultâneas em massa ao servidor.

Regularmente há novas versões disponíveis para o Serviço do Azure SignalR e, às vezes, patches ou atualizações de todo o Azure, causando ocasionalmente interrupções de nossos serviços relacionados. Esses eventos podem causar curtos períodos de interrupção do serviço, mas se no lado do cliente existir um mecanismo de desconexão/reconexão, o impacto será mínimo, assim como qualquer desconexão/reconexão causada pelo cliente.

Esta seção descreve as várias causas da queda da conexão do servidor e fornece algumas diretrizes sobre como identificar a causa raiz.

Possíveis erros no lado do servidor

  • [Error]Connection "..." to the service was dropped
  • The remote party closed the WebSocket connection without completing the close handshake
  • Service timeout. 30000.00ms elapsed without receiving a message from service.

Causa raiz

A conexão do serviço do servidor foi fechada pelo ASRS(Azure SignalRService).

O tempo limite excedido do ping pode ser causado pelo uso alto de CPU ou pela privação do pool de threads no lado do servidor.

Para o ASP.NET SignalR, um problema conhecido foi corrigido no SDK 1.6.0. Atualize seu SDK para a versão mais recente.

Privação do pool de threads

Se o servidor estiver sem pool de threads, isso significa que nenhuma thread está funcionando no processamento de mensagens. Todas as threads não estão respondendo com um determinado método.

Normalmente esse cenário é causado por métodos assíncronos sobre síncronos ou por Task.Result/Task.Wait() métodos assíncronos.

Consulte práticas recomendadas de desempenho do ASP.NET Core.

Conheça mais sobre a privação do pool de threads.

Como detectar a privação do pool de threads

Verifique a contagem de threads. Se não houver picos nesse momento, execute estas etapas:

  • Se estiver usando o Serviço de Aplicativo do Azure, verifique a contagem de threads nas métricas. Verifique a agregação Max:

    Screenshot of the Max thread count pane in Azure App Service.

  • Se estiver usando o .NET Framework, você pode encontrar as métricas no monitor de desempenho na VM do servidor.

  • Se estiver usando o .NET Core em um contêiner, consulte Coletar diagnósticos em contêineres.

Você também pode usar código para detectar a privação do pool de threads:

public class ThreadPoolStarvationDetector : EventListener
{
    private const int EventIdForThreadPoolWorkerThreadAdjustmentAdjustment = 55;
    private const uint ReasonForStarvation = 6;

    private readonly ILogger<ThreadPoolStarvationDetector> _logger;

    public ThreadPoolStarvationDetector(ILogger<ThreadPoolStarvationDetector> logger)
    {
        _logger = logger;
    }

    protected override void OnEventSourceCreated(EventSource eventSource)
    {
        if (eventSource.Name == "Microsoft-Windows-DotNETRuntime")
        {
            EnableEvents(eventSource, EventLevel.Informational, EventKeywords.All);
        }
    }

    protected override void OnEventWritten(EventWrittenEventArgs eventData)
    {
        // See: https://learn.microsoft.com/dotnet/framework/performance/thread-pool-etw-events#threadpoolworkerthreadadjustmentadjustment
        if (eventData.EventId == EventIdForThreadPoolWorkerThreadAdjustmentAdjustment &&
            eventData.Payload[2] as uint? == ReasonForStarvation)
        {
            _logger.LogWarning("Thread pool starvation detected!");
        }
    }
}

Adicione ao serviço:

service.AddSingleton<ThreadPoolStarvationDetector>();

Depois, verifique o log quando a conexão do servidor for desconectada pelo tempo limite excedido do ping.

Como encontrar a causa raiz da privação do pool de threads

Para encontrar a causa raiz da privação do pool de threads:

  • Faça o despejo de memória e, em seguida, analise a pilha de chamadas. Para obter mais informações, consulte Coletar e analisar despejos de memória.
  • Use clrmd para despejar a memória quando a privação do pool de threads for detectada. Em seguida, registre a pilha de chamadas.

Guia de Solução de Problemas

  1. Abra o log do servidor de aplicativo para verificar se algo anormal ocorreu.
  2. Verifique o log de eventos do servidor do aplicativo para ver se o servidor de aplicativos foi reiniciado.
  3. Crie um incidente. Forneça o período e nos envie um email com o nome do recurso.

Está com problemas ou tem comentários sobre a solução de problemas? Fale conosco.

Dicas

Como visualizar a solicitação de saída do cliente?

Analise um exemplo do ASP.NET Core (o do ASP.NET é semelhante):

  • No navegador: usando o Chrome como exemplo, você pode usar F12 para abrir a janela do console e alternar para a guia Rede. Talvez seja necessário atualizar a página usando F5 para capturar a rede desde o início.

    Chrome View Network

  • Do cliente C#:

    Você pode visualizar os tráfegos locais da Web usando o Fiddler. Os tráfegos de WebSocket são compatíveis a partir do Fiddler 4.5.

    Fiddler View Network

Como reiniciar a conexão do cliente?

Abaixo estão os Exemplos de códigos que contêm a lógica de reinicialização da conexão com a estratégia SEMPRE REENVIE:

Está com problemas ou tem comentários sobre a solução de problemas? Fale conosco.

Próximas etapas

Neste guia, você aprendeu sobre como tratar os problemas comuns. Aprenda mais métodos genéricos de solução de problemas.