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 Hub
s, 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
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
Lançar exceções CLR
Veja as exceções lançadas ao depurar o código do servidor do aplicativo:
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 clienteSkipNegotiation
é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
- Abra o log do servidor do aplicativo para ver se algo anormal ocorreu
- Verifique o log de eventos do servidor do aplicativo para ver se o servidor do aplicativo foi reiniciado
- 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.
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
- Lembre-se de fechar a conexão do cliente se você usar clientes SignalR na função do Azure ou usar o cliente SignalR como um singleton.
- Em vez de usar clientes SignalR na função Azure, você pode criar clientes SignalR em qualquer outro lugar e usar Ligações do Azure Functions para o Serviço SignalR do Azure para negociar o cliente para o Azure SignalR. E você também pode utilizar a vinculação para enviar mensagens. Exemplos para negociar o cliente e enviar mensagens podem ser encontrados aqui. Mais informações podem ser encontradas aqui.
- Quando você usa clientes SignalR na função do Azure, pode haver uma arquitetura melhor para o seu cenário. Verifique se você projeta uma arquitetura sem servidor adequada. Você pode consultar aplicativos sem servidor em tempo real com as associações do Serviço SignalR no Azure Functions.
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: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
- Abra o log do servidor do aplicativo para ver se algo anormal ocorreu.
- Verifique o log de eventos do servidor do aplicativo para ver se o servidor do aplicativo foi reiniciado.
- 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.
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.
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.