Przewodnik rozwiązywania problemów z typowymi problemami z usługą Azure SignalR Service

Ten artykuł zawiera wskazówki dotyczące rozwiązywania niektórych typowych problemów, które mogą napotkać klienci.

Token dostępu za długi

Możliwe błędy

  • Po stronie klienta ERR_CONNECTION_
  • 414 Identyfikator URI jest za długi
  • 413 Zbyt duży ładunek
  • Token dostępu nie może być dłuższy niż 4K. 413 Jednostka żądania jest za duża

Główna przyczyna

W przypadku protokołu HTTP/2 maksymalna długość pojedynczego nagłówka wynosi 4 K, więc jeśli używasz przeglądarki do uzyskiwania dostępu do usługi platformy Azure, wystąpi błąd ERR_CONNECTION_ dla tego ograniczenia.

W przypadku klientów HTTP/1.1 lub C# maksymalna długość identyfikatora URI wynosi 12 K, maksymalna długość nagłówka wynosi 16 K.

W przypadku zestawu SDK w wersji 1.0.6 lub nowszej /negotiate zostanie zgłoszony, 413 Payload Too Large gdy wygenerowany token dostępu jest większy niż 4 K.

Rozwiązanie

Domyślnie oświadczenia z context.User.Claims są uwzględniane podczas generowania tokenu dostępu JWT do usługi ASRS (Azure SignalRService), dzięki czemu oświadczenia są zachowywane i mogą być przekazywane z usługi ASRS do Hub usługi , gdy klient nawiązuje połączenie z usługą Hub.

W niektórych przypadkach context.User.Claims służy do przechowywania wielu informacji dla serwera aplikacji, z których większość nie jest używana przez Hubskładniki, ale przez inne składniki.

Wygenerowany token dostępu jest przekazywany przez sieć, a w przypadku połączeń Protokołu WebSocket/SSE tokeny dostępu są przekazywane przez ciągi zapytań. Najlepszym rozwiązaniem jest więc przekazanie tylko niezbędnych oświadczeń od klienta przez usługę ASRS do serwera aplikacji, gdy centrum wymaga.

ClaimsProvider Istnieje możliwość dostosowania oświadczeń przekazywanych do usługi ASRS wewnątrz tokenu dostępu.

W przypadku ASP.NET Core:

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

W przypadku ASP.NET:

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

Masz problemy lub opinie dotyczące rozwiązywania problemów? Daj nam znać.

Wymagany protokół TLS 1.2

Możliwe błędy

  • błąd ASP.NET "Brak dostępnego serwera" #279
  • ASP.NET "Połączenie nie jest aktywne, nie można wysłać danych do usługi"." Błąd 324
  • "Wystąpił błąd podczas wykonywania żądania HTTP do https://<API endpoint>. Ten błąd może być spowodowany tym, że certyfikat serwera nie został prawidłowo skonfigurowany za pomocą protokołu HTTP.SYS w przypadku protokołu HTTPS. Ten błąd może być również spowodowany niezgodnością powiązania zabezpieczeń między klientem a serwerem".

Główna przyczyna

Usługa platformy Azure obsługuje tylko protokół TLS1.2 w przypadku problemów z zabezpieczeniami. W przypadku platformy .NET Framework istnieje możliwość, że protokół TLS1.2 nie jest protokołem domyślnym. W związku z tym nie można pomyślnie ustanowić połączeń serwera z usługą ASRS.

Przewodnik po rozwiązywaniu problemów

  1. Jeśli ten błąd można odtworzyć lokalnie, usuń zaznaczenie pola Wyboru Tylko mój kod i wyrzuć wszystkie wyjątki CLR i debuguj serwer aplikacji lokalnie, aby zobaczyć, jaki wyjątek zgłasza.

    • Usuń zaznaczenie pola wyboru Tylko mój kod

      Uncheck Just My Code

    • Zgłaszanie wyjątków CLR

      Throw CLR exceptions

    • Zobacz wyjątki zgłaszane podczas debugowania kodu po stronie serwera aplikacji:

      Exception throws

  2. W przypadku ASP.NET można również dodać następujący kod do elementu Startup.cs , aby włączyć szczegółowe śledzenie i zobaczyć błędy z dziennika.

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

Rozwiązanie

Dodaj następujący kod do uruchamiania:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Masz problemy lub opinie dotyczące rozwiązywania problemów? Daj nam znać.

400 Bad Request returned for client requests (Błąd 400 — Nieprawidłowe żądanie zwracany w przypadku żądań klientów)

Główna przyczyna

Sprawdź, czy żądanie klienta ma wiele hub ciągów zapytania. hub parametr jest zachowanym parametrem zapytania, a wartość 400 zostanie wyrzucona, jeśli usługa wykryje więcej niż jeden hub w zapytaniu.

Masz problemy lub opinie dotyczące rozwiązywania problemów? Daj nam znać.

Błąd 401 — brak autoryzacji zwracany w przypadku żądań klientów

Główna przyczyna

Obecnie wartość domyślna okresu istnienia tokenu JWT wynosi jedną (1) godzinę.

W przypadku ASP.NET Core SignalR, gdy używa typu transportu WebSocket, jest to ok.

W przypadku innych typów transportu ASP.NET Core SignalR, SSE i long-polling domyślny okres istnienia domyślnie połączenie może trwać najwyżej przez jedną godzinę.

W przypadku usługi ASP.NET SignalR klient wysyła /ping żądanie "zachowaj żywą" do usługi od czasu do czasu, gdy /ping awaria zakończy się niepowodzeniem, klient przerywa połączenie i nigdy nie łączy się ponownie. W przypadku ASP.NET SignalR domyślny okres istnienia tokenu powoduje, że połączenie trwa przez co najwyżej godzinę dla całego typu transportu.

Rozwiązanie

W przypadku problemów z zabezpieczeniami rozszerzenie czasu wygaśnięcia nie jest zachęcane. Zalecamy dodanie logiki ponownego połączenia od klienta w celu ponownego uruchomienia połączenia w przypadku wystąpienia takiego połączenia 401. Po ponownym uruchomieniu połączenia klient będzie negocjował z serwerem aplikacji w celu ponownego pobrania tokenu JWT i uzyskania odnowionego tokenu.

Sprawdź tutaj , jak ponownie uruchomić połączenia klienckie.

Masz problemy lub opinie dotyczące rozwiązywania problemów? Daj nam znać.

Błąd 404 zwracany w przypadku żądań klientów

W przypadku trwałego połączenia usługi SignalR najpierw /negotiate z usługą Azure SignalR, a następnie ustanawia rzeczywiste połączenie z usługą Azure SignalR.

Przewodnik po rozwiązywaniu problemów

  • Poniżej przedstawiono sposób wyświetlania wychodzących żądań w celu pobrania żądania od klienta do usługi.
  • Sprawdź adres URL żądania, gdy wystąpi błąd 404. Jeśli adres URL jest przeznaczony dla aplikacji internetowej i podobny do {your_web_app}/hubs/{hubName}, sprawdź, czy klient SkipNegotiation ma wartość true. Klient otrzymuje adres URL przekierowania podczas pierwszego negocjowania z serwerem aplikacji. Klient nie może pominąć negocjacji podczas korzystania z usługi Azure SignalR.
  • Kolejne 404 może wystąpić, gdy żądanie połączenia jest obsługiwane ponad pięć (5) sekund po /negotiate wywołaniu. Sprawdź sygnaturę czasową żądania klienta i otwórz dla nas problem, jeśli żądanie do usługi ma powolną odpowiedź.

Masz problemy lub opinie dotyczące rozwiązywania problemów? Daj nam znać.

404 zwrócone dla żądania ponownego połączenia usługi SignalR ASP.NET

W przypadku ASP.NET SignalR, gdy połączenie klienta spadnie, ponownie nawiąże połączenie przy użyciu tego samego connectionId przez trzy razy przed zatrzymaniem połączenia. /reconnect Może pomóc, jeśli połączenie zostało przerwane z powodu sporadycznych problemów z siecią, które /reconnect mogą pomyślnie ponownie opublikować trwałe połączenie. W innych okolicznościach na przykład połączenie klienta jest przerywane z powodu porzuconego połączenia z serwerem kierowanym lub usługa SignalR Service ma pewne błędy wewnętrzne, takie jak ponowne uruchomienie wystąpienia/tryb failover/wdrożenie, połączenie już nie istnieje, dlatego /reconnect zwraca wartość 404. Jest to oczekiwane zachowanie dla /reconnect i po trzech ponownych próbach połączenia zostanie zatrzymane. Zalecamy użycie logiki ponownego uruchomienia połączenia po zatrzymaniu połączenia.

Masz problemy lub opinie dotyczące rozwiązywania problemów? Daj nam znać.

429 (Zbyt wiele żądań) zwracanych dla żądań klientów

Są dwa przypadki.

Liczba połączeń współbieżnych przekracza limit

W przypadku wystąpień bezpłatnych limit liczby połączeń współbieżnych wynosi 20 w przypadku wystąpień standardowych, limit liczby połączeń współbieżnych na jednostkę wynosi 1 K, co oznacza, że jednostka100 zezwala na 100 K połączeń współbieżnych.

Połączenia obejmują zarówno połączenia klienta, jak i serwera. Sprawdź tutaj , jak są liczone połączenia.

Zbyt wiele żądań negocjowania w tym samym czasie

Zalecamy losowe opóźnienie przed ponownym nawiązaniem połączenia. Sprawdź tutaj, czy nie ma próbek ponawiania próbek.

Masz problemy lub opinie dotyczące rozwiązywania problemów? Daj nam znać.

Błąd 500 podczas negocjowania: usługa Azure SignalR Service nie jest jeszcze połączona. Spróbuj ponownie później

Główna przyczyna

Ten błąd jest zgłaszany, gdy nie ma połączenia serwera z usługą Azure SignalR Service.

Przewodnik po rozwiązywaniu problemów

Włącz śledzenie po stronie serwera, aby dowiedzieć się szczegółów błędu podczas próby nawiązania połączenia z usługą Azure SignalR Service.

Włączanie rejestrowania po stronie serwera dla ASP.NET Core SignalR

Rejestrowanie po stronie serwera dla ASP.NET Core SignalR integruje się z ILogger rejestrowaniem opartym na platformie ASP.NET Core. Rejestrowanie po stronie serwera można włączyć przy użyciu metody ConfigureLogging, przykładowe użycie w następujący sposób:

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

Kategorie rejestratora dla usługi Azure SignalR zawsze zaczynają się od Microsoft.Azure.SignalR. Aby włączyć szczegółowe dzienniki z usługi Azure SignalR, skonfiguruj poprzednie prefiksy na Debug poziom w pliku appsettings.json , jak pokazano poniżej:

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

Włączanie śladów po stronie serwera dla ASP.NET SignalR

W przypadku korzystania z wersji >zestawu SDK = 1.0.0można włączyć śledzenie, dodając następujące informacje do web.config: (Szczegóły)

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

Masz problemy lub opinie dotyczące rozwiązywania problemów? Daj nam znać.

Przerywanie połączenia klienta

Gdy klient jest połączony z usługą Azure SignalR, trwałe połączenie między klientem a usługą Azure SignalR może czasami spaść z różnych powodów. W tej sekcji opisano kilka możliwości powodujących takie upuszczanie połączenia i przedstawiono wskazówki dotyczące identyfikowania głównej przyczyny.

Możliwe błędy widoczne po stronie 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."}

Główna przyczyna

Połączenia klienta mogą spaść w różnych okolicznościach:

  • W przypadku Hub zgłaszania wyjątków z żądaniem przychodzącym
  • Gdy połączenie z serwerem, z którym klient został przekierowany, spadnie, zobacz poniższą sekcję, aby uzyskać szczegółowe informacje na temat przerywania połączenia z serwerem
  • Gdy występuje problem z łącznością sieciową między klientem a usługą SignalR Service
  • Gdy usługa SignalR Service zawiera błędy wewnętrzne, takie jak ponowne uruchomienie wystąpienia, przejście w tryb failover, wdrożenie itd.

Przewodnik po rozwiązywaniu problemów

  1. Otwórz dziennik po stronie serwera aplikacji, aby sprawdzić, czy wystąpiły jakiekolwiek nietypowe zdarzenia
  2. Sprawdź dziennik zdarzeń po stronie serwera aplikacji, aby sprawdzić, czy serwer aplikacji został uruchomiony ponownie
  3. Utwórz dla nas problem z udostępnieniem przedziału czasu i wyślij do nas wiadomość e-mail z nazwą zasobu

Masz problemy lub opinie dotyczące rozwiązywania problemów? Daj nam znać.

Stale zwiększa się połączenie klienta

Może to być spowodowane nieprawidłowym użyciem połączenia klienta. Jeśli ktoś zapomni zatrzymać/usunąć klienta SignalR, połączenie pozostanie otwarte.

Możliwe błędy widoczne w metrykach usługi SignalR w sekcji Monitorowanie menu zasobów witryny Azure Portal

Połączenia klientów stale rosną przez długi czas w metrykach usługi Azure SignalR.

Client connection increasing constantly

Główna przyczyna

Połączenie DisposeAsync klienta usługi SignalR nigdy nie jest wywoływane, połączenie jest otwarte.

Przewodnik po rozwiązywaniu problemów

Sprawdź, czy klient usługi SignalR nigdy nie zamyka się.

Rozwiązanie

Sprawdź, czy zamykasz połączenie. Ręcznie wywołaj metodę HubConnection.DisposeAsync() , aby zatrzymać połączenie po jego użyciu.

Na przykład:

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

Typowe nieprawidłowe użycie połączenia klienta

Przykład funkcji platformy Azure

Ten problem często występuje, gdy ktoś ustanawia połączenie klienta usługi SignalR w metodzie funkcji platformy Azure zamiast tworzenia statycznej składowej w klasie funkcji. Możesz oczekiwać, że zostanie nawiązane tylko jedno połączenie klienta, ale zamiast tego liczba połączeń klienta stale rośnie w metrykach. Wszystkie te połączenia upuszczają się dopiero po ponownym uruchomieniu usługi Azure Function lub Azure SignalR. To zachowanie jest spowodowane tym, że w przypadku każdego żądania funkcja platformy Azure tworzy jedno połączenie klienta, a jeśli nie zatrzymasz połączenia klienta w metodzie funkcji, klient utrzymuje połączenia aktywne z usługą Azure SignalR Service.

Rozwiązanie

Masz problemy lub opinie dotyczące rozwiązywania problemów? Daj nam znać.

Przerywanie połączenia z serwerem

Po uruchomieniu serwera aplikacji w tle zestaw Azure SDK rozpoczyna inicjowanie połączeń serwera ze zdalnym usługą Azure SignalR. Zgodnie z opisem w temacie Internals of Azure SignalR Service (Wewnętrzne elementy usługi Azure SignalR Service) usługa Azure SignalR kieruje przychodzące ruch klientów do tych połączeń serwera. Po usunięciu połączenia z serwerem wszystkie obsługiwane przez niego połączenia klienckie również zostaną zamknięte.

Ponieważ połączenia między serwerem aplikacji i usługą SignalR Service są trwałymi połączeniami, mogą wystąpić problemy z łącznością sieciową. W zestawie SDK serwera mamy strategię Zawsze ponownie nawiązuj połączenie z połączeniami serwera. Najlepszym rozwiązaniem jest również zachęcanie użytkowników do dodawania logiki ciągłego ponownego łączenia do klientów z losowym czasem opóźnienia, aby uniknąć ogromnych równoczesnych żądań do serwera.

Regularnie są dostępne nowe wersje usługi Azure SignalR Service, a czasami poprawki lub uaktualnienia na całej platformie Azure lub od czasu do czasu przerywają pracę naszych usług zależnych. Te zdarzenia mogą spowodować krótki okres przerw w działaniu usługi, ale jeśli po stronie klienta występuje mechanizm rozłączania/ponownego nawiązywania połączenia, efekt jest minimalny, podobnie jak po stronie klienta, co spowodowało ponowne połączenie po stronie klienta.

W tej sekcji opisano kilka możliwości prowadzących do upuszczania połączenia z serwerem i przedstawiono wskazówki dotyczące identyfikowania głównej przyczyny.

Możliwe błędy widoczne po stronie serwera

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

Główna przyczyna

Połączenie z usługą serwera jest zamykane przez usługę ASRS (A zure SignalRService).

W przypadku przekroczenia limitu czasu ping może to być spowodowane wysokim użyciem procesora CPU lub głodem puli wątków po stronie serwera.

W przypadku ASP.NET SignalR znany problem został rozwiązany w zestawie SDK 1.6.0. Uaktualnij zestaw SDK do najnowszej wersji.

Głodowanie puli wątków

Jeśli serwer głoduje, oznacza to, że żadne wątki nie pracują nad przetwarzaniem komunikatów. Wszystkie wątki nie odpowiadają w określonej metodzie.

Zwykle ten scenariusz jest spowodowany przez synchronizację asynchronizową lub Task.Result/Task.Wait() przez metody asynchroniczne.

Zobacz najlepsze rozwiązania dotyczące wydajności ASP.NET Core.

Zobacz więcej na temat głodu puli wątków.

Jak wykryć głodowanie puli wątków

Sprawdź liczbę wątków. Jeśli w tym czasie nie ma żadnych skoków, wykonaj następujące kroki:

  • Jeśli używasz usługi aplikacja systemu Azure, sprawdź liczbę wątków w metrykach. Sprawdź agregację Max :

    Screenshot of the Max thread count pane in Azure App Service.

  • Jeśli używasz programu .NET Framework, możesz znaleźć metryki w monitorze wydajności na maszynie wirtualnej serwera.

  • Jeśli używasz platformy .NET Core w kontenerze, zobacz Zbieranie diagnostyki w kontenerach.

Możesz również użyć kodu do wykrywania głodu puli wątków:

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

Dodaj ją do usługi:

service.AddSingleton<ThreadPoolStarvationDetector>();

Następnie sprawdź dziennik po rozłączeniu połączenia z serwerem przez przekroczenie limitu czasu polecenia ping.

Jak znaleźć główną przyczynę głodu puli wątków

Aby znaleźć główną przyczynę głodu puli wątków:

  • Zrzuć pamięć, a następnie przeanalizuj stos wywołań. Aby uzyskać więcej informacji, zobacz Zbieranie i analizowanie zrzutów pamięci.
  • Użyj polecenia clrmd , aby zrzucić pamięć po wykryciu głodu puli wątków. Następnie zarejestruj stos wywołań.

Przewodnik po rozwiązywaniu problemów

  1. Otwórz dziennik po stronie serwera aplikacji, aby sprawdzić, czy wystąpiły jakiekolwiek nietypowe zdarzenia.
  2. Sprawdź dziennik zdarzeń po stronie serwera aplikacji, aby sprawdzić, czy serwer aplikacji został uruchomiony ponownie.
  3. Utwórz problem. Podaj przedział czasu i wyślij do nas wiadomość e-mail z nazwą zasobu.

Masz problemy lub opinie dotyczące rozwiązywania problemów? Daj nam znać.

Wskazówki

Jak wyświetlić żądanie wychodzące od klienta?

Weź ASP.NET Core na przykład (ASP.NET jeden jest podobny):

  • W przeglądarce: jako przykład możesz użyć przeglądarki F12 , aby otworzyć okno konsoli, a następnie przełączyć się na kartę Sieć . Może być konieczne odświeżenie strony przy użyciu klawisza F5 w celu przechwycenia sieci od samego początku.

    Chrome View Network

  • Z poziomu klienta języka C#:

    Lokalne ruchy internetowe można wyświetlać przy użyciu programu Fiddler. Ruch protokołu WebSocket jest obsługiwany od wersji Fiddler 4.5.

    Fiddler View Network

Jak ponownie uruchomić połączenie klienta?

Oto przykładowe kody zawierające logikę ponownego uruchamiania połączenia ze strategią ALWAYS RETRY:

Masz problemy lub opinie dotyczące rozwiązywania problemów? Daj nam znać.

Następne kroki

W tym przewodniku przedstawiono sposób obsługi typowych problemów. Możesz również dowiedzieć się więcej ogólnych metod rozwiązywania problemów.