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 cliente
ERR_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 Hub
s, 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
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
Lance as exceções CLR
Consulte as exceções lançadas ao depurar o código do lado do servidor do aplicativo:
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 clienteSkipNegotiation
é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 ILogger
registro 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
- Abra o log do servidor de aplicativo para verificar se algo anormal ocorreu
- Verifique o log de eventos do servidor do aplicativo para ver se o servidor de aplicativos foi reiniciado
- 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.
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
- Lembre-se de fechar a conexão do cliente se usar clientes do SignalR no Azure Function ou usar o cliente do SignalR como um singleton.
- Em vez de usar clientes do SignalR no Azure Function, você pode criar clientes do SignalR em qualquer outro lugar e usar Associações do Azure Functions para o Serviço do Azure SignalR para negociar o cliente do Azure SignalR. Também pode utilizar a associação para enviar mensagens. Exemplos para negociar clientes e enviar mensagens podem ser encontrados aqui. Confira mais informações aqui.
- Se estiver usando clientes do SignalR no Azure Function, pode haver uma arquitetura melhor para o seu cenário. Verifique se projetou uma arquitetura sem servidor adequada. Você pode consultar Aplicativos sem servidor em tempo real com associações do Serviço do SignalR no Azure Functions.
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
: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
- Abra o log do servidor de aplicativo para verificar se algo anormal ocorreu.
- Verifique o log de eventos do servidor do aplicativo para ver se o servidor de aplicativos foi reiniciado.
- 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.
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.
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.