Condividi tramite


Guida alla risoluzione di problemi comuni del Servizio Azure SignalR

Questo articolo fornisce indicazioni sulla risoluzione dei problemi per alcuni problemi comuni che i clienti potrebbero riscontrare.

Token di accesso troppo lungo

Possibili errori

  • ERR_CONNECTION_ lato client
  • 414 - URI richiesta troppo lungo
  • 413 Payload Too Large
  • Il token di accesso non deve essere più lungo di 4K. 413 Entità della richiesta troppo grande

Causa principale

Per HTTP/2, la lunghezza massima per una singola intestazione è 4 K, quindi se si usa il browser per accedere al servizio di Azure, si verifica un errore ERR_CONNECTION_ per questa limitazione.

Per HTTP/1.1 o client C#, la lunghezza massima dell'URI è 12 K e la lunghezza massima dell'intestazione è 16 K.

Con la versione dell'SDK 1.0.6 o successiva, /negotiate restituisce 413 Payload Too Large quando il token di accesso generato è più grande di 4 K.

Soluzione

Per impostazione predefinita, le attestazioni dacontext.User.Claims sono incluse durante la generazione del token di accesso JWT per ASRS (Azure SignalR Service), in modo che le attestazioni vengano mantenute e possano essere passate da ASRS a Hub quando il client si connette a Hub.

In alcuni casi, si usano context.User.Claims per archiviare numerose informazioni per il server app, la maggior parte delle quali non viene usata da Hubma da altri componenti.

Il token di accesso generato viene passato attraverso la rete e per le connessioni WebSocket/SSE i token di accesso vengono passati tramite stringhe di query. Pertanto, come procedura consigliata, è consigliabile passare solo attestazioni necessarie dal client tramite ASRS al server app quando l'hub lo richiede.

Esiste un ClaimsProvider per personalizzare le attestazioni che passano ad ASRS all'interno del token di accesso.

Per ASP.NET Core:

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

Per ASP.NET:

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

Problemi o feedback sulla risoluzione dei problemi? Segnalarli.

TLS 1.2 obbligatorio

Possibili errori

  • Errore "Nessun server disponibile" #279 di ASP.NET
  • Errore "La connessione non è attiva. I dati non possono essere inviati al servizio" #324 di ASP.NET
  • "Si è verificato un errore durante l'esecuzione della richiesta HTTP per https://<API endpoint>. Questo errore può verificarsi se il certificato del server non è configurato correttamente con HTTP.SYS nel caso HTTPS. La causa possibile di questo errore è una mancata corrispondenza del binding di sicurezza tra il client e il server."

Causa principale

Il servizio di Azure supporta solo TLS1.2 per problemi di sicurezza. Con .NET Framework, è possibile che TLS1.2 non sia il protocollo predefinito. Di conseguenza, le connessioni server ad ASRS non possono essere stabilite correttamente.

Guida alla risoluzione dei problemi

  1. Se questo errore può essere riprodotto localmente, deselezionare Just My Code, generare tutte le eccezioni CLR ed eseguire il debug del server app in locale per vedere quali eccezioni generano.

    • Deselezionare Just My Code

      Deselezionare Just My Code

    • Generare eccezioni CLR

      Generare eccezioni CLR

    • Vedere le eccezioni generate durante il debug del codice sul lato server dell'app:

      Eccezione generata

  2. Per ASP.NET, è anche possibile aggiungere il codice seguente a Startup.cs per abilitare la traccia dettagliata e visualizzare gli errori dal log.

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

Soluzione

Aggiungere il codice seguente all'avvio:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Problemi o feedback sulla risoluzione dei problemi? Segnalarli.

Errore 400 Richiesta non valida restituito per le richieste del client

Causa principale

Controllare se la richiesta client include più stringhe di query hub. hub è il parametro di query mantenuto e se il servizio rileva più hub nella query, restituisce un errore 400.

Problemi o feedback sulla risoluzione dei problemi? Segnalarli.

401 - Non autorizzata restituito per le richieste client

Causa principale

Attualmente il valore predefinito della durata del token JWT è un'ora (1).

Per ASP.NET Core SignalR, quando usa il tipo di trasporto WebSocket, è OK.

Per altro tipo di trasporto ASP.NET Core SignalR, SSE e polling lungo, la durata predefinita implica per impostazione che la connessione può persistere al massimo per un'ora.

Per ASP.NET SignalR, il client invia una richiesta "keep alive" /ping al servizio di tanto in tanto; quando /ping non riesce, il client interrompe la connessione e non si riconnette mai. Per ASP.NET SignalR, la durata predefinita del token fa sì che la connessione duri al massimo un'ora per tutto il tipo di trasporto.

Soluzione

Per problemi di sicurezza, TTL è sconsigliato. È consigliabile aggiungere logica di riconnessione dal client per riavviare la connessione quando si verifica tale errore 401. Quando il client riavvia la connessione, negozia con il server app per ottenere nuovamente il token JWT e ottenere un token rinnovato.

Controllare qui per informazioni su come riavviare le connessioni client.

Problemi o feedback sulla risoluzione dei problemi? Segnalarli.

404 restituito per le richieste client

Per una connessione persistente di SignalR, prima /negotiate al servizio Azure SignalR e quindi stabilisce la connessione reale al servizio Azure SignalR.

Guida alla risoluzione dei problemi

  • Come visualizzare le richieste in uscita per ottenere la richiesta dal client al servizio.
  • Controllare l'URL della richiesta quando si verifica l'errore 404. Se l'URL è destinato all'app Web ed è simile a {your_web_app}/hubs/{hubName}, verificare se il client SkipNegotiation è true. Il client riceve un URL di reindirizzamento quando negozia per la prima volta con il server app. Il client non deve ignorare la negoziazione quando si usa Azure SignalR.
  • Un altro errore 404 può verificarsi quando la richiesta di connessione viene gestita più di cinque (5) secondi dopo la chiamata di /negotiate. Controllare il timestamp della richiesta client e aprire un problema con Microsoft se la richiesta al servizio ha una risposta lenta.

Problemi o feedback sulla risoluzione dei problemi? Segnalarli.

Errore 404 restituito per la richiesta di riconnessione di ASP.NET SignalR

Per ASP.NET SignalR, quando la connessione client si interrompe, si riconnette usando lo stesso connectionId per tre volte prima di arrestare la connessione. /reconnect può essere utile se la connessione viene interrotta a causa di problemi intermittenti di rete per cui /reconnect può ristabilire correttamente la connessione persistente. In altre circostanze, ad esempio, la connessione client viene si interrompe a causa dell'interruzione della connessione al server indirizzato oppure il servizio SignalR presenta alcuni errori interni come riavvio dell'istanza, failover o distribuzione. La connessione non esiste più, pertanto /reconnect restituisce 404. Si tratta del comportamento previsto per /reconnect e dopo tre tentativi la connessione si arresta. È consigliabile una logica di riavvio della connessione quando la connessione si arresta.

Problemi o feedback sulla risoluzione dei problemi? Segnalarli.

Errore 429 (Troppe richieste) restituite per le richieste client

I casi possibili sono due:

Il numero di connessioni simultanee è superiore al limite

Per istanze gratuite, il limite del numero di connessioni simultanee è 20. Per istanze Standard, il limite del numero di connessioni simultanee per unità è 1 K, vale a dire che Unit100 consente 100.000 connessioni simultanee.

Le connessioni includono connessioni sia client che server. Fare clic qui per scoprire come vengono conteggiate le connessioni.

NegotiateThrottled

Quando troppi client negoziano richieste contemporaneamente, potrebbe esserci un limite. Il limite è correlato al numero di unità che hanno un limite più elevato. Inoltre, è consigliabile un ritardo casuale prima della riconnessione; controllare qui per gli esempi di ripetizione dei tentativi.

Problemi o feedback sulla risoluzione dei problemi? Segnalarli.

Errore 500 durante la negoziazione: il servizio Azure SignalR non è ancora connesso. Riprovare più tardi

Causa principale

Questo errore viene segnalato quando non esiste alcuna connessione server al servizio Azure SignalR connesso.

Guida alla risoluzione dei problemi

Abilitare la traccia lato server per individuare i dettagli dell'errore quando il server tenta di connettersi al servizio Azure SignalR.

Abilitare la registrazione lato server per ASP.NET Core SignalR

La registrazione lato server per ASP.NET Core SignalR si integra con ILogger basato sulla registrazione fornito nel framework ASP.NET Core. È possibile abilitare la registrazione lato server usando ConfigureLogging, un utilizzo di esempio come indicato di seguito:

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

Le categorie di logger per Azure SignalR iniziano sempre con Microsoft.Azure.SignalR. Per abilitare log dettagliati da Azure SignalR, configurare i prefissi precedenti per livello Debug nel file appsettings.json; vedere l'esempio seguente:

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

Abilitare le tracce lato server per ASP.NET SignalR

Quando si usa la versione dell'SDK >= 1.0.0, è possibile abilitare le tracce aggiungendo quanto segue a web.config: (Dettagli)

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

Problemi o feedback sulla risoluzione dei problemi? Segnalarli.

La connessione client si interrompe

Quando il client è connesso ad Azure SignalR, la connessione persistente tra il client e Azure SignalR a volte può interrompersi per diversi motivi. Questa sezione descrive diverse possibilità che causano tale interruzione della connessione e fornisce indicazioni su come identificare la causa radice.

Possibili errori rilevati dal lato client

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

Le connessioni client possono interrompersi in varie circostanze:

  • Quando Hub genera eccezioni con la richiesta in ingresso
  • Quando la connessione al server, a cui il client viene indirizzato, si interrompe; vedere la sezione seguente per informazioni dettagliate sulle interruzioni della connessione al server
  • Quando si verifica un problema di connettività di rete tra il client e il servizio SignalR
  • Quando il servizio SignalR presenta alcuni errori interni, ad esempio riavvio dell'istanza, failover, distribuzione e così via

Guida alla risoluzione dei problemi

  1. Aprire il log lato server dell'app per verificare se si è verificato un evento anomalo
  2. Controllare il registro eventi lato server app per verificare se il server app è stato riavviato
  3. Creare un problema con Microsoft per fornire l'intervallo di tempo e inviare un'e-mail a Microsoft con il nome della risorsa

Problemi o feedback sulla risoluzione dei problemi? Segnalarli.

La connessione client aumenta costantemente

Il motivo potrebbe essere l'utilizzo improprio della connessione client. Se qualcuno dimentica di arrestare/eliminare il client SignalR, la connessione rimane aperta.

Possibili errori rilevati dalle metriche di SignalR nella sezione Monitoraggio del menu delle risorse del portale di Azure

Le connessioni client aumentano costantemente per molto tempo nelle metriche di Azure SignalR.

Connessione client in costante aumento

Causa principale

DisposeAsync della connessione client SignalR non viene mai chiamato e la connessione rimane aperta.

Guida alla risoluzione dei problemi

Controllare se il client SignalR non si chiude mai.

Soluzione

Controllare se si chiude la connessione. Chiamare manualmente HubConnection.DisposeAsync() per arrestare la connessione dopo l'uso.

Ad esempio:

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

Utilizzo improprio non corretto della connessione client

Esempio di Funzioni di Azure

Questo problema si verifica spesso quando qualcuno stabilisce una connessione client SignalR in un metodo di Funzioni di Azure anziché renderlo un membro statico nella classe della funzione. Ci si potrebbe aspettare che venga stabilita una sola connessione client, ma si nota invece che il numero di connessioni client aumenta costantemente nelle metriche. Tutte queste connessioni si interrompono solo dopo il riavvio del servizio Azure SignalR o Funzioni di Azure. Questo comportamento si verifica perché Funzioni di Azure stabilisce una connessione client per ogni richiesta e se non si arresta la connessione client nel metodo della funzione, il client mantiene attive le connessioni al servizio Azure SignalR.

Soluzione

Problemi o feedback sulla risoluzione dei problemi? Segnalarli.

La connessione al server si interrompe

All'avvio del server app, in background, Azure SDK inizia ad avviare le connessioni server ad Azure SignalR remoto. Come descritto in Elementi interni di Azure SignalR Service, Azure SignalR instrada i traffico client in ingresso a queste connessioni server. Quando una connessione server si interrompe, chiude tutte le connessioni client che stava gestendo.

Poiché le connessioni tra il server app e il servizio SignalR sono connessioni persistenti, potrebbero verificarsi problemi di connettività di rete. In Server SDK è disponibile una strategia Always Reconnect per le connessioni server. Come procedura consigliata, è preferibile anche che gli utenti aggiungano logica di riconnessione continua ai client con un ritardo casuale per evitare richieste simultanee massicce al server.

Sono disponibili regolarmente nuovi rilasci di versioni per il servizio Azure SignalR e talvolta con l'applicazione di patch o aggiornamenti a livello di Azure occasionalmente si interrompono i servizi dipendenti. Questi eventi potrebbero causare un breve periodo di interruzione del servizio, ma se esiste un meccanismo di disconnessione/riconnessione lato client, l'effetto è minimo come qualsiasi disconnessione/riconnessione causata lato client.

Questa sezione descrive diverse possibilità che causano l'interruzione della connessione al server e fornisce indicazioni su come identificare la causa radice.

Possibili errori rilevati dal lato server

  • [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 principale

La connessione al servizio server viene chiusa da ASRS (Azure SignalR Service).

L'utilizzo elevato della CPU o l'insufficienza delle risorse del pool di thread lato server potrebbe causare un timeout del ping.

Per ASP.NET SignalR, un problema noto è stato risolto in SDK 1.6.0. Aggiornare l'SDK alla versione più recente.

Insufficienza delle risorse del pool di thread

Se le risorse del server sono insufficienti, nessun thread sta lavorando all'elaborazione dei messaggi. Tutti i thread non rispondono in un determinato metodo.

Normalmente, nei metodi asincroni, un'asincronia nella sincronizzazione per Task.Result/Task.Wait() causa questo scenario.

Vedere la Procedure consigliate per le prestazioni di ASP.NET Core.

Vedere altre informazioni sull'insufficienza delle risorse del pool di thread.

Come rilevare l'insufficienza delle risorse del pool di thread

Controllare il numero di thread. Se non sono presenti picchi in quel momento, eseguire questi passaggi:

  • Se si usa il Servizio app di Azure, controllare il numero di thread nelle metriche. Controllare l'aggregazione Max:

    Screenshot del riquadro Numero massimo di thread nel Servizio app di Azure.

  • Se si usa .NET Framework, è possibile trovare metriche nel monitoraggio delle prestazioni nella VM del server.

  • Se si usa .NET Core in un contenitore, vedere Raccogliere la diagnostica nei contenitori.

È anche possibile usare il codice per rilevare l'insufficienza delle risorse del pool di thread:

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!");
        }
    }
}

Aggiungerlo al servizio:

service.AddSingleton<ThreadPoolStarvationDetector>();

Controllare quindi il log quando il server è disconnesso a causa del timeout del ping.

Come trovare la causa radice dell'insufficienza delle risorse del pool di thread

Per trovare la causa radice dell'insufficienza delle risorse del pool di thread:

  • Eseguire il dump della memoria e quindi analizzare lo stack di chiamate. Per altre informazioni, vedere Raccogliere e analizzare i dump di memoria.
  • Usare clrmd per eseguire il dump della memoria quando viene rilevata l'insufficienza delle risorse del pool di thread. Registrare quindi lo stack di chiamate.

Guida alla risoluzione dei problemi

  1. Aprire il log lato server app per verificare se si è verificato un evento anomalo.
  2. Controllare il registro eventi lato server app per verificare se il server app è stato riavviato.
  3. Creare un problema. Fornire l'intervallo di tempo e inviare un'e-mail a Microsoft con il nome della risorsa.

Problemi o feedback sulla risoluzione dei problemi? Segnalarli.

Suggerimenti

Come visualizzare la richiesta in uscita dal client?

Usare ASP.NET Core One per esempio (ASP.NET One è simile):

  • Dal browser: usare Chrome come esempio; è possibile usare F12 per aprire la finestra della console e passare alla scheda Rete. Potrebbe essere necessario aggiornare la pagina usando F5 per acquisire la rete fin dall'inizio.

    Rete di visualizzazione di Chrome

  • Dal client C#:

    È possibile visualizzare i traffico Web locale usando Fiddler. Il traffico WebSocket è supportato a partire da Fiddler 4.5.

    Rete di visualizzazione di Fiddler

Come riavviare la connessione client?

Di seguito sono riportati codici di esempio contenenti la logica di connessione di riavvio con strategia ALWAYS RETRY:

Problemi o feedback sulla risoluzione dei problemi? Segnalarli.

Passaggi successivi

In questa guida si è appreso come gestire problemi comuni. È possibile apprendere anche altri metodi di risoluzione di problemi generici.