Compartilhar via


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 para um único cabeçalho é 4 mil, então, se estiver usando um navegador para acessar o serviço Azure, há um erro ERR_CONNECTION_ para essa limitação.

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

Com a versão do SDK 1.0.6 ou superior, /negotiate gera 413 Payload Too Large quando o token de acesso gerado é maior 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 SignalR Service), para que as declarações sejam preservadas e possam ser passadas do ASRS para 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? Queremos saber.

Necessário TLS 1.2

Possíveis erros

  • Erro #279 “Nenhum servidor disponível” do ASP.NET
  • ASP.NET "A conexão não está ativa, os dados não podem ser enviados para o serviço." erro #324
  • "Ocorreu um erro ao fazer a solicitação HTTP para https://<API endpoint>. Esse erro pode ocorrer se o certificado do servidor não estiver configurado corretamente com HTTP.SYS no caso de HTTPS. A possível causa desse erro é uma incompatibilidade da vinculaçã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

      Desmarque Apenas Meu Código

    • Lance as exceções CLR

      Lance as exceções CLR

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

      A exceção é lançada

  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? Queremos saber.

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. O hub é um parâmetro de consulta preservado e, se o serviço detectar mais de um hub na consulta, ele retornará um erro 400.

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

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 obter 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? Queremos saber.

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? Queremos saber.

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 é descartada devido à conexão do servidor roteado ser descartada, ou o Serviço SignalR ter alguns erros internos como reinicialização/failover/implantação de instância. A 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? Queremos saber.

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âneas por 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.

NegotiateThrottled

Quando há muitas solicitações de negociação de clientes ao mesmo tempo, ele pode ser limitado. O limite está relacionado ao número de unidades, quanto mais unidades, maior o limite. Além disso, sugerimos adicionar um atraso aleatório antes de reconectar, verifique aqui para exemplos de repetição.

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

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 seu arquivo appsettings.json, veja o exemplo a seguir:

{
    "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? Queremos saber.

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 a qual o cliente foi roteado, cair, veja a seção a seguir 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? Queremos saber.

As conexões do cliente aumentam constantemente

Uso inadequado da conexão do cliente pode causar isso. Se alguém esquecer de parar/descartar o SignalR do cliente, a conexão permanecerá aberta.

Erros possíveis observados nas métricas do SignalR que estão na seção de 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.

As conexões do cliente aumentam constantemente

Causa raiz

A DisposeAsync conexão do cliente nunca é chamada e 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, em vez disso, vê o número de conexões de clientes 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 a Função do Azure estabelece uma conexão de cliente para cada solicitação, e se você não encerrar a conexão do cliente no método da função, o cliente mantém as conexões ativas para o serviço Azure SignalR.

Solução

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

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. Quando uma conexão do servidor é interrompida, todas as conexões de clientes que estavam sendo atendidas são fechadas.

Como as conexões entre o servidor de aplicativos e o Serviço SignalR são conexões persistentes, elas podem experimentar 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 um curto período de interrupção do serviço, mas desde que o lado do cliente tenha um mecanismo de desconexão/reconexão, o efeito é mínimo como qualquer desconexão-reconexão causada pelo lado do 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 é fechada pelo ASRS(AZURE SignalR Service).

Uso elevado de CPU ou esgotamento do pool de threads no lado do servidor pode causar um tempo limite de ping.

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, em métodos assíncronos, assíncrono sobre síncrono ou por Task.Result/Task.Wait() causa esse cenário.

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:

    Captura de tela do painel de contagem máxima de threads no Serviço de Aplicativo do Azure.

  • 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>();

Em seguida, verifique seu log quando o servidor foi desconectado devido ao tempo limite de 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? Queremos saber.

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.

    Visualização da Rede do Chrome

  • 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.

    Visualização da Rede do Fiddler

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.