Partilhar via


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

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

Token de acesso muito longo

Possíveis erros

  • Do lado do cliente ERR_CONNECTION_
  • 414 URI muito longo
  • 413 Payload Demasiado Grande
  • O Token de Acesso não deve ter mais de 4K. 413 Entidade de Pedido Demasiado Grande

Causa raiz

Para HTTP/2, o comprimento máximo para um único cabeçalho é 4K, portanto, se estiver usando o navegador para acessar o serviço do Azure, há um erro ERR_CONNECTION_ para essa limitação.

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

Com o SDK versão 1.0.6 ou superior, /negotiate lança quando o token de 413 Payload Too Large acesso gerado é maior que 4 K.

Solução

Por padrão, as declarações de são incluídas ao gerar o token de context.User.Claims acesso JWT para ASRS(Azure S ignalR S ervice), para que as declarações sejam preservadase possam ser passadasde ASRS para quando Hub o cliente se conectar ao Hub.

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

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

Há um ClaimsProvider para você personalizar as declarações que passam para 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(...);
            });

Tem problemas ou comentários sobre a solução de problemas? Deixe-nos saber.

TLS 1.2 necessário

Possíveis erros

  • ASP.NET Erro "Nenhum servidor disponível" #279
  • 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 HTTPS. A possível causa desse erro é uma incompatibilidade da ligação de segurança entre o cliente e o servidor."

Causa raiz

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

Guia de resolução de problemas

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

    • Desmarque Apenas o meu código

      Desmarque Apenas o meu código

    • Lançar exceções CLR

      Lançar exceções CLR

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

      Lançamentos de exceção

  2. Para ASP.NET, você também pode adicionar o seguinte código 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;

Tem problemas ou comentários sobre a solução de problemas? Deixe-nos saber.

400 Bad Request returned for client requests (Devolvido o erro 400 Pedido Incorreto para pedidos de cliente)

Causa raiz

Verifique se a solicitação do cliente tem várias hub cadeias de caracteres de consulta. O hub parâmetro de consulta é preservado e, se o serviço detetar mais de um hub na consulta, ele retornará um erro 400.

Tem problemas ou comentários sobre a solução de problemas? Deixe-nos saber.

401 Unauthorized returned for client requests (Erro 401 não autorizado devolvido para pedidos de cliente)

Causa raiz

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

Para ASP.NET Core SignalR, quando ele estiver usando o tipo de transporte WebSocket, tudo bem.

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

Para ASP.NET SignalR, o cliente envia uma /ping solicitação de "manter vivo" para o serviço de tempos em tempos, quando o /ping falha, o cliente aborta a conexão e nunca mais se reconecta. Para 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

Por questões de segurança, estender o TTL não é incentivado. Sugerimos adicionar lógica de reconexão do cliente para reiniciar a conexão quando tal 401 ocorrer. 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.

Verifique aqui como reiniciar as conexões do cliente.

Tem problemas ou comentários sobre a solução de problemas? Deixe-nos saber.

404 returned for client requests (404 devolvido para pedidos de cliente)

Para uma conexão persistente do SignalR, ele primeiro /negotiate para o serviço Azure SignalR e, em seguida, estabelece a conexão real com o serviço Azure SignalR.

Guia de resolução de problemas

  • Seguindo Como visualizar 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 semelhante ao {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 do aplicativo. O cliente não deve ignorar a negociação ao usar o Azure SignalR.
  • Outros 404 podem acontecer quando a solicitação de conexão é tratada mais de cinco (5) segundos após /negotiate a chamada. Verifique o carimbo de data/hora do pedido do cliente e abra-nos um problema se o pedido ao serviço tiver uma resposta lenta.

Tem problemas ou comentários sobre a solução de problemas? Deixe-nos saber.

404 retornado para ASP.NET solicitação de reconexão do SignalR

Para ASP.NET SignalR, quando a conexão do cliente cai, ele se reconecta usando o mesmo connectionId por três vezes antes de interromper a conexão. /reconnect pode ajudar se a conexão for interrompida devido a problemas intermitentes de rede que /reconnect podem 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 tem alguns erros internos, como reinicialização/failover/implantação da instância. A conexão não existe mais, portanto /reconnect , retorna 404. É o comportamento esperado para /reconnect e depois de três vezes repetir a conexão para. Sugerimos ter uma lógica de reinicialização da conexão quando a conexão parar.

Tem problemas ou comentários sobre a solução de problemas? Deixe-nos saber.

429 (Demasiados pedidos) devolvidos para pedidos de clientes

Existem dois casos.

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

Para instâncias Livres, o limite de contagem de conexões simultâneas é 20 Para instâncias Standard, o limite de contagem de conexões simultâneas por unidade é 1 K, o que significa que Unit100 permite conexões simultâneas de 100 K.

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

NegociarAcelerado

Quando há muitos clientes negociando solicitações ao mesmo tempo, isso pode ficar limitado. O limite refere-se à contagem de unidades que mais unidades têm um limite mais elevado. Além disso, sugerimos ter um atraso aleatório antes de se reconectar, verifique aqui as amostras de repetição.

Tem problemas ou comentários sobre a solução de problemas? Deixe-nos saber.

Erro 500 ao negociar: O Serviço 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 com o Serviço SignalR do Azure conectado.

Guia de resolução de problemas

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

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

O log do lado do servidor para ASP.NET Core SignalR integra-se com o ILogger log baseado fornecido na estrutura ASP.NET Core. Você pode habilitar o log do lado do servidor usando ConfigureLogging, um exemplo de uso da seguinte maneira:

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

As categorias de logger para o Azure SignalR sempre começam com Microsoft.Azure.SignalR. Para habilitar logs detalhados do Azure SignalR, configure os prefixos anteriores para nivelar Debug em seu arquivo de appsettings.json , consulte o exemplo a seguir:

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

Habilitar rastreamentos do lado do servidor para ASP.NET SignalR

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

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

Tem problemas ou comentários sobre a solução de problemas? Deixe-nos saber.

A conexão do cliente cai

Quando o cliente está conectado ao Azure SignalR, a conexão persistente entre o cliente e o Azure SignalR às vezes pode cair por motivos diferentes. Esta seção descreve várias possibilidades que causam essa queda de conexão e fornece algumas orientações sobre como identificar a causa raiz.

Possíveis erros vistos do 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 lança exceções com a solicitação de entrada
  • Quando a conexão do servidor, para a qual o cliente foi roteado, cair, consulte a seção a seguir para obter detalhes sobre a conexão do servidor cair
  • Quando ocorre um problema de conectividade de rede entre o cliente e o Serviço SignalR
  • Quando o Serviço SignalR tem alguns erros internos, como reinicialização de instância, failover, implantação e assim por diante

Guia de resolução de problemas

  1. Abra o log do servidor do aplicativo para ver se algo anormal ocorreu
  2. Verifique o log de eventos do servidor do aplicativo para ver se o servidor do aplicativo foi reiniciado
  3. Crie um problema para nós fornecendo o período de tempo e envie o nome do recurso por e-mail para nós

Tem problemas ou comentários sobre a solução de problemas? Deixe-nos saber.

A conexão do cliente aumenta constantemente

O uso inadequado da conexão do cliente pode causar isso. Se alguém se esquecer de parar/eliminar o cliente SignalR, a ligação permanece aberta.

Possíveis erros vistos nas 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 tempo nas métricas do Azure SignalR.

Conexão com o cliente aumentando constantemente

Causa raiz

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

Guia de resolução de problemas

Verifique se o cliente SignalR nunca fecha.

Solução

Verifique se você fecha a conexão. Ligue HubConnection.DisposeAsync() manualmente para interromper a conexão depois de usá-lo.

Por exemplo:

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

Uso inadequado comum da conexão do cliente

Exemplo de Função do Azure

Esse problema geralmente ocorre quando alguém estabelece uma conexão de cliente SignalR em um método de função do Azure em vez de torná-lo um membro estático na classe de função. Você pode esperar que apenas uma conexão de cliente seja estabelecida, mas, em vez disso, você vê a contagem de conexões de cliente aumentar constantemente em métricas. Todas essas conexões caem somente depois que a Função do Azure ou o serviço Azure SignalR é reiniciado. Esse comportamento ocorre porque o Azure Function estabelece uma conexão de cliente para cada solicitação e, se você não parar a conexão do cliente no método de função, o cliente manterá as conexões ativas para o serviço Azure SignalR.

Solução

Tem problemas ou comentários sobre a solução de problemas? Deixe-nos saber.

A conexão do servidor cai

Quando o servidor de aplicativos é iniciado, em segundo plano, o SDK do Azure começa a iniciar conexões de servidor com o Azure SignalR remoto. Conforme descrito em Internos do Serviço SignalR do Azure, o Azure SignalR roteia os tráfegos de entrada do cliente para essas conexões de servidor. Quando uma conexão de servidor é descartada, ela fecha todas as conexões de cliente que estava servindo.

Como as conexões entre o servidor de aplicativos e o Serviço SignalR são conexões persistentes, eles podem enfrentar problemas de conectividade de rede. No SDK do servidor, temos uma estratégia Always Reconnect para conexões de servidor. Como prática recomendada, 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 massivas ao servidor.

Regularmente, há novas versões para o Serviço Azure SignalR e, às vezes, patches ou atualizações em todo o Azure ou ocasionalmente interrupções de nossos serviços dependentes. Esses eventos podem trazer 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 várias possibilidades que levam à queda de conexão do servidor e fornece algumas orientações sobre como identificar a causa raiz.

Possíveis erros vistos do 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 servidor-serviço é fechada por ASRS(Azure SignalR Service).

O alto uso da CPU ou a inanição do pool de threads no lado do servidor podem causar um tempo limite de ping.

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

Fome na piscina de fios

Se o seu servidor está morrendo de fome, isso significa que nenhum thread está trabalhando no processamento de mensagens. Todos os threads não estão respondendo em um determinado método.

Normalmente, em métodos assíncronos, assíncrono sobre sincronização ou por Task.Result/Task.Wait() causa desse cenário.

Consulte ASP.NET Principais práticas recomendadas de desempenho.

Veja mais sobre a fome na piscina de fios.

Como detetar a fome do pool de threads

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

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

    Captura de ecrã do painel Contagem máxima de threads no Serviço de Aplicações do Azure.

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

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

Você também pode usar o código para detetar a fome 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-o ao seu 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 fome do pool de threads

Para encontrar a causa raiz da fome do pool de threads:

  • Despeje a 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 fome do pool de threads for detetada. Em seguida, registre a pilha de chamadas.

Guia de resolução de problemas

  1. Abra o log do servidor do aplicativo para ver se algo anormal ocorreu.
  2. Verifique o log de eventos do servidor do aplicativo para ver se o servidor do aplicativo foi reiniciado.
  3. Crie um problema. Forneça o período de tempo e envie o nome do recurso por e-mail para nós.

Tem problemas ou comentários sobre a solução de problemas? Deixe-nos saber.

Sugestões

Como visualizar o pedido de saída do cliente?

Tomemos ASP.NET Core um por exemplo (ASP.NET um é semelhante):

  • Do navegador: Tome 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.

    Rede de visualização do Chrome

  • Do cliente C#:

    Você pode visualizar o tráfego da Web local usando o Fiddler. Os tráfegos WebSocket são suportados desde o Fiddler 4.5.

    Rede Fiddler View

Como reiniciar a conexão do cliente?

Aqui estão os códigos de exemplo que contêm a lógica de conexão de reinicialização com a estratégia ALWAYS RETRY:

Tem problemas ou comentários sobre a solução de problemas? Deixe-nos saber.

Próximos passos

Neste guia, você aprendeu sobre como lidar com os problemas comuns. Você também pode aprender métodos de solução de problemas mais genéricos.