Průvodce odstraňováním potíží pro běžné problémy se službou Azure SignalR

Tento článek obsahuje pokyny k řešení potíží s některými běžnými problémy, se kterými se zákazníci můžou setkat.

Přístupový token je příliš dlouhý

Možné chyby

  • Na straně klienta ERR_CONNECTION_
  • 414 Příliš dlouhý identifikátor URI
  • 413 Příliš velká datová část
  • Přístupový token nesmí být delší než 4K. 413 – Entita požadavku je příliš velká

Původní příčina

U protokolu HTTP/2 je maximální délka jedné hlavičky 4 K, takže pokud pro přístup ke službě Azure používáte prohlížeč, dojde k chybě ERR_CONNECTION_ pro toto omezení.

U klientů HTTP/1.1 nebo C# je maximální délka identifikátoru URI 12 K a maximální délka hlavičky je 16 K.

S sadou SDK verze 1.0.6 nebo vyšší se vyvolá413 Payload Too Large, /negotiate když je vygenerovaný přístupový token větší než 4 K.

Řešení

Ve výchozím nastavení jsou deklarace identity zahrnuté context.User.Claims při generování přístupového tokenu JWT do ASRS(Azure SignalR Service), aby se deklarace identity zachovaly a mohly být předány ze služby ASRS do Hub služby, když se klient připojí k Hub.

V některých případech context.User.Claims se používá k ukládání velkého množství informací pro aplikační server, z nichž většina se nepoužívá Hub, ale jinými komponentami.

Vygenerovaný přístupový token se předává přes síť a pro připojení WebSocket/SSE se přístupové tokeny předávají prostřednictvím řetězců dotazů. Jako osvědčený postup doporučujeme předávat pouze nezbytné deklarace identity od klienta prostřednictvím ASRS na aplikační server, když centrum potřebuje.

ClaimsProvider V rámci přístupového tokenu můžete přizpůsobit deklarace identity předávané službě ASRS.

Pro ASP.NET Core:

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

Pro ASP.NET:

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

Máte problémy nebo zpětnou vazbu k řešení potíží? Dejte nám vědět.

Vyžaduje se protokol TLS 1.2.

Možné chyby

  • ASP.NET chyba "Není k dispozici server" č. 279
  • ASP.NET "Připojení není aktivní, data se nedají odeslat do služby." Chyba č. 324
  • Došlo k chybě při provádění požadavku HTTP na https://<API endpoint>adresu . K této chybě může dojít v případě, že certifikát serveru není správně nakonfigurovaný s HTTP.SYS v případě HTTPS. Možnou příčinou této chyby je neshoda vazby zabezpečení mezi klientem a serverem."

Původní příčina

Služba Azure podporuje pouze protokol TLS1.2 z hlediska zabezpečení. V rozhraní .NET Framework je možné, že protokol TLS1.2 není výchozím protokolem. V důsledku toho není možné úspěšně navázat připojení serveru k ASRS.

Příručka pro řešení problémů

  1. Pokud se tato chyba dá reprodukovat místně, zrušte zaškrtnutí políčka Jen můj kód a vyvolejte všechny výjimky CLR a ladit aplikační server místně, abyste zjistili, jaká výjimka se vyvolá.

    • Zrušit zaškrtnutí políčka Jen můj kód

      Zrušit zaškrtnutí políčka Jen můj kód

    • Vyvolání výjimek CLR

      Vyvolání výjimek CLR

    • Podívejte se na výjimky vyvolané laděním kódu na straně serveru aplikace:

      Vyvolání výjimek

  2. Pro ASP.NET můžete také přidat následující Startup.cs kód, který povolí podrobné trasování a zobrazí chyby z protokolu.

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

Řešení

Do spouštěcího programu přidejte následující kód:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Máte problémy nebo zpětnou vazbu k řešení potíží? Dejte nám vědět.

Požadavky klientů vrací chybu 400 Chybný požadavek

Původní příčina

Zkontrolujte, jestli váš požadavek klienta obsahuje více hub řetězců dotazu. Parametr hub dotazu se zachová a pokud služba zjistí více než jeden hub v dotazu, vrátí chybu 400.

Máte problémy nebo zpětnou vazbu k řešení potíží? Dejte nám vědět.

Požadavky klientů vrací chybu 401 Neautorizováno

Původní příčina

Výchozí hodnota životnosti tokenu JWT je v současné době jedna (1) hodina.

Pro ASP.NET Core SignalR je při použití typu přenosu WebSocket v pořádku.

Pro ASP.NET základního typu přenosu, SSE a dlouhé dotazování znamená výchozí životnost ve výchozím nastavení, že připojení může maximálně jednu hodinu trvat.

V případě služby ASP.NET SignalR klient odešle /ping do služby od času požadavek "Udržet naživu", když dojde /ping k chybě, klient přeruší připojení a nikdy se znovu nepřipojí. Pro ASP.NET SignalR výchozí doba života tokenu způsobí, že připojení trvá maximálně jednu hodinu pro všechny typy přenosu.

Řešení

Pokud jde o zabezpečení, rozšíření hodnoty TTL se nepodporuje. Doporučujeme přidat logiku opětovného připojení z klienta, aby se připojení restartoval, když dojde k 401. Když klient restartuje připojení, vyjedná s aplikačním serverem, aby znovu získal token JWT a získal obnovený token.

Tady zjistíte, jak restartovat připojení klientů.

Máte problémy nebo zpětnou vazbu k řešení potíží? Dejte nám vědět.

Požadavky klientů vrací chybu 404 Neautorizováno

V případě trvalého připojení SignalR nejprve /negotiate ke službě Azure SignalR a pak vytvoří skutečné připojení ke službě Azure SignalR.

Příručka pro řešení problémů

  • Následující postup zobrazení odchozích požadavků pro získání požadavku z klienta do služby.
  • Zkontrolujte adresu URL požadavku, když dojde k chybě 404. Pokud adresa URL cílí na vaši webovou aplikaci a podobně, {your_web_app}/hubs/{hubName}zkontrolujte, jestli je trueklient SkipNegotiation . Klient obdrží adresu URL pro přesměrování, když se poprvé vyjedná s aplikačním serverem. Klient nesmí při použití Azure SignalR přeskočit vyjednávání.
  • K dalšímu počtu 404 může dojít, když se žádost o připojení zpracuje déle než pět (5) sekund po /negotiate zavolání. Zkontrolujte časové razítko požadavku klienta a otevřete problém, pokud má požadavek na službu pomalou odpověď.

Máte problémy nebo zpětnou vazbu k řešení potíží? Dejte nám vědět.

404 vráceno pro žádost o opětovné připojení služby SignalR pro ASP.NET

V případě ASP.NET SignalR se po ukončení připojení klienta znovu připojí po connectionId dobu tříkrát, než připojení zastaví. /reconnect může pomoct, pokud dojde k přerušení připojení kvůli přerušovaným problémům se sítí, které /reconnect můžou trvalé připojení úspěšně obnovit. Za jiných okolností se například připojení klienta zahodí kvůli ukončení připojení ke směrovanému serveru nebo služba SignalR obsahuje některé vnitřní chyby, jako je restartování instance, převzetí služeb při selhání nebo nasazení. Spojení již neexistuje, proto /reconnect vrátí 404. Jedná se o očekávané chování a /reconnect po třech opakováních připojení se zastaví. Doporučujeme mít logiku restartování připojení, když se připojení zastaví.

Máte problémy nebo zpětnou vazbu k řešení potíží? Dejte nám vědět.

429 (příliš mnoho požadavků) vrácených pro požadavky klientů

Existují dva možné případy.

Počet souběžných připojení překračuje limit

V případě bezplatných instancí je limit počtu souběžných připojení 20 Pro standardní instance, limit počtu souběžných připojení na jednotku je 1 K, což znamená, že jednotka 100 umožňuje 100 K souběžných připojení.

Připojení zahrnují připojení klienta i serveru. Tady zkontrolujte, jak se počítá připojení.

NegotiateThrottled

Pokud je současně vyjednáno příliš mnoho klientů, může dojít k omezení. Limit se vztahuje k počtu jednotek, které mají více jednotek vyšší limit. Kromě toho doporučujeme mít náhodné zpoždění před opětovným připojením, zkontrolujte tady ukázky opakování.

Máte problémy nebo zpětnou vazbu k řešení potíží? Dejte nám vědět.

Chyba 500 při vyjednávání: Služba Azure SignalR ještě není připojená, zkuste to prosím znovu později.

Původní příčina

Tato chyba se zobrazí, když není připojené připojení serveru ke službě Azure SignalR.

Příručka pro řešení problémů

Povolte trasování na straně serveru a zjistěte podrobnosti o chybě, když se server pokusí připojit ke službě Azure SignalR.

Povolení protokolování na straně serveru pro ASP.NET Core SignalR

Protokolování na straně serveru pro ASP.NET Core SignalR se integruje s protokolováním založeným ILogger na ASP.NET Core Frameworku. Protokolování na straně serveru můžete povolit pomocí ConfigureLoggingukázkového použití následujícím způsobem:

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

Kategorie protokolovacího modulu pro Azure SignalR vždy začínají .Microsoft.Azure.SignalR Pokud chcete povolit podrobné protokoly z Azure SignalR, nakonfigurujte předchozí předpony na Debug úroveň v souboru appsettings.json, viz následující příklad:

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

Povolení trasování na straně serveru pro ASP.NET SignalR

Při použití verze >sady SDK = 1.0.0můžete povolit trasování přidáním následujícího příkazu: web.config(Podrobnosti)

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

Máte problémy nebo zpětnou vazbu k řešení potíží? Dejte nám vědět.

Zahodí připojení klienta

Když je klient připojený k Azure SignalR, trvalé připojení mezi klientem a Službou Azure SignalR může někdy z různých důvodů klesat. Tato část popisuje několik možností, které způsobují takové výpadky připojení, a obsahuje některé pokyny k identifikaci původní příčiny.

Možné chyby na straně klienta

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

Původní příčina

Klientská připojení můžou za různých okolností klesat:

  • Při Hub vyvolání výjimek s příchozím požadavkem
  • Když se připojení k serveru, na které klient směroval, zahodí, podrobnosti o ukončení připojení k serveru najdete v následující části.
  • Když dojde k problému s připojením k síti mezi klientem a službou SignalR Service
  • Pokud má služba SignalR několik vnitřních chyb, jako je restartování instance, převzetí služeb při selhání, nasazení atd.

Příručka pro řešení problémů

  1. Otevřete protokol na straně serveru aplikace a zjistěte, jestli se něco neobvyklého neproběhla.
  2. Zkontrolujte protokol událostí na straně serveru aplikace a zjistěte, jestli se aplikační server restartoval.
  3. Vytvořte problém, který nám poskytne časový rámec, a pošlete nám e-mailem název prostředku.

Máte problémy nebo zpětnou vazbu k řešení potíží? Dejte nám vědět.

Připojení klienta se neustále zvyšuje.

Nesprávné použití připojení klienta může způsobit jeho použití. Pokud někdo zapomene zastavit nebo odstranit klienta SignalR, připojení zůstane otevřené.

Možné chyby zobrazené v metrikách služby SignalR v části Monitorování v nabídce prostředků webu Azure Portal

Klientská připojení se v metrikách Azure SignalR neustále zvyšuje po dlouhou dobu.

Neustále se zvyšuje připojení klienta.

Původní příčina

Připojení DisposeAsync klienta SignalR se nikdy nevolá a připojení zůstane otevřené.

Příručka pro řešení problémů

Zkontrolujte, jestli se klient SignalR nikdy nezavře .

Řešení

Zkontrolujte, jestli připojení zavřete. Po použití připojení ručně zastavte HubConnection.DisposeAsync() volání.

Příklad:

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

Běžné nesprávné využití připojení klienta

Příklad funkce Azure Functions

K tomuto problému často dochází, když někdo vytvoří připojení klienta SignalR v metodě funkce Azure místo toho, aby se jedná o statického člena ve třídě funkce. Můžete očekávat, že bude navázáno pouze jedno připojení klienta, ale místo toho se počet připojení klienta neustále zvyšuje v metrikách. Všechna tato připojení se zahodí až po restartování služby Azure Functions nebo služby Azure SignalR. K tomuto chování dochází, protože funkce Azure Vytvoří pro každý požadavek jedno připojení klienta a pokud v metodě funkce nezastavíte připojení klienta, klient udržuje připojení aktivní ke službě Azure SignalR.

Řešení

  • Nezapomeňte zavřít připojení klienta, pokud ve funkci Azure používáte klienty SignalR nebo jako jednoúčelový klient signalR.
  • Místo použití klientů SignalR ve funkci Azure můžete vytvářet klienty SignalR kdekoli jinde a pomocí vazeb Azure Functions pro službu Azure SignalR vyjednávat klienta s Azure SignalR. K odesílání zpráv můžete také využít vazbu. Ukázky pro vyjednávání klientů a odesílání zpráv najdete tady. Další informace najdete tady.
  • Pokud ve funkci Azure používáte klienty SignalR, může být pro váš scénář lepší architektura. Zkontrolujte, jestli navrhujete správnou bezserverovou architekturu. V azure Functions můžete odkazovat na bezserverové aplikace v reálném čase pomocí vazeb služby SignalR Service.

Máte problémy nebo zpětnou vazbu k řešení potíží? Dejte nám vědět.

Zahodí připojení k serveru

Když se aplikační server spustí, na pozadí se sada Azure SDK začne inicializovat připojení serveru ke vzdálené službě Azure SignalR. Jak je popsáno v interních informacích služby Azure SignalR, Azure SignalR směruje příchozí klientské přenosy na tato připojení k serveru. Když dojde k vyřazení připojení k serveru, zavře všechna klientská připojení, která obsluhovala.

Vzhledem k tomu, že připojení mezi aplikačním serverem a službou SignalR Service jsou trvalá připojení, můžou nastat problémy s připojením k síti. V sadě Server SDK máme strategii always reconnect to server connections. (Vždy znovu připojit k připojení k serveru). Doporučujeme také uživatelům přidat logiku průběžného opětovného připojení k klientům s náhodným zpožděním, aby se zabránilo masivním souběžným požadavkům na server.

Pravidelně existují nové verze pro službu Azure SignalR a někdy i opravy nebo upgrady pro Celou Azure nebo občas přerušení závislých služeb. Tyto události můžou způsobit krátkou dobu přerušení služeb, ale pokud má klientská strana mechanismus odpojení nebo opětovného připojení, je účinek minimální, stejně jako jakékoli přerušení připojení na straně klienta.

Tato část popisuje několik možností, které vedou k poklesu připojení k serveru, a obsahuje některé pokyny k identifikaci původní příčiny.

Možné chyby na straně serveru

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

Původní příčina

Připojení služby serveru je uzavřeno službou ASRS(A zure SignalR Service).

Vysoké využití procesoru nebo hladový fond vláken na straně serveru může způsobit vypršení časového limitu příkazu ping.

Pro ASP.NET SignalR byl známý problém opravený v sadě SDK 1.6.0. Upgradujte sadu SDK na nejnovější verzi.

Hladový fond vláken

Pokud váš server hladověl, znamená to, že na zpracování zpráv nefungují žádná vlákna. Všechna vlákna v určité metodě nereagují.

V asynchronních metodách obvykle async over sync nebo způsobuje Task.Result/Task.Wait() tento scénář.

Podívejte se na osvědčené postupy ASP.NET core pro výkon.

Přečtěte si další informace o hladovění fondu vláken.

Zjištění hladovění fondu vláken

Zkontrolujte počet vláken. Pokud v té době nejsou žádné špičky, proveďte tyto kroky:

  • Pokud používáte službu Aplikace Azure Service, zkontrolujte počet vláken v metrikách. Max Zkontrolujte agregaci:

    Snímek obrazovky s podoknem Maximální počet vláken ve službě Aplikace Azure Service

  • Pokud používáte rozhraní .NET Framework, najdete metriky v monitorování výkonu na virtuálním počítači serveru.

  • Pokud v kontejneru používáte .NET Core, přečtěte si téma Shromažďování diagnostiky v kontejnerech.

K detekci hladovění fondu vláken můžete použít také kód:

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://video2.skills-academy.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!");
        }
    }
}

Přidejte ho do služby:

service.AddSingleton<ThreadPoolStarvationDetector>();

Potom zkontrolujte protokol, když se server odpojil kvůli vypršení časového limitu příkazu ping.

Jak najít původní příčinu hladovění fondu vláken

Zjištění původní příčiny hladovění fondu vláken:

  • Vypněte paměť a pak analyzujte zásobník volání. Další informace naleznete v tématu Shromažďování a analýza výpisů paměti.
  • Příkaz clrmd slouží k výpisu paměti při zjištění hladovění fondu vláken. Pak protokolujte zásobník volání.

Příručka pro řešení problémů

  1. Otevřete protokol na straně serveru aplikace a podívejte se, jestli se něco neobvyklého neproběhla.
  2. Zkontrolujte protokol událostí na straně serveru aplikace a zjistěte, jestli se aplikační server restartoval.
  3. Vytvořte problém. Zadejte časový rámec a pošlete nám e-mailem název prostředku.

Máte problémy nebo zpětnou vazbu k řešení potíží? Dejte nám vědět.

Tipy

Jak zobrazit odchozí požadavek od klienta?

Vezměte ASP.NET Core jeden například (ASP.NET jeden je podobný):

  • V prohlížeči: Jako příklad můžete použít F12 k otevření okna konzoly a přepnutí na kartu Síť . Možná budete muset aktualizovat stránku pomocí klávesy F5 , aby se síť zachytála od začátku.

    Síť zobrazení chromu

  • Z klienta jazyka C#:

    Místní webové přenosy můžete zobrazit pomocí Fiddleru. Přenosy protokolu WebSocket jsou podporované od verze Fiddler 4.5.

    Fiddler View Network

Jak restartovat připojení klienta?

Tady jsou ukázkové kódy obsahující logiku restartování připojení se strategií ALWAYS RETRY :

Máte problémy nebo zpětnou vazbu k řešení potíží? Dejte nám vědět.

Další kroky

V této příručce jste se dozvěděli, jak řešit běžné problémy. Můžete se také dozvědět více obecných metod řešení potíží.