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ępuje błąd ERR_CONNECTION_
dotyczący tego ograniczenia.
W przypadku klientów HTTP/1.1 lub C# maksymalna długość identyfikatora URI wynosi 12 K, a maksymalna długość nagłówka wynosi 16 K.
W przypadku zestawu SDK w wersji 1.0.6 lub nowszej jest zgłaszany413 Payload Too Large
, /negotiate
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 SignalR Service), 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 Hub
skł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 wystąpić, jeśli certyfikat serwera nie został prawidłowo skonfigurowany przy użyciu HTTP.SYS w przypadku protokołu HTTPS. Możliwą przyczyną tego błędu jest niezgodność 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
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
Zgłaszanie wyjątków CLR
Zobacz wyjątki zgłaszane podczas debugowania kodu po stronie serwera aplikacji:
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. Parametr hub
jest zachowywany, a jeśli usługa wykryje więcej niż jeden hub
w zapytaniu, zwraca błąd 400.
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. Gdy klient ponownie uruchomi połączenie, negocjuje z serwerem aplikacji, aby ponownie pobrać token JWT i uzyskać odnowiony token.
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 klientSkipNegotiation
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 wewnętrzne błędy, takie jak ponowne uruchomienie wystąpienia/przejście w 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.
NegotiateThrottled
Jeśli w tym samym czasie istnieje zbyt wiele klientów negocjuje żądania, może on zostać ograniczony. Limit odnosi się do liczby jednostek, które mają większy limit. Oprócz tego 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 , zobacz następujący przykład:
{
"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.0
moż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 serwera, z którym klient został przekierowany, spadnie, zobacz następującą 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
- Otwórz dziennik po stronie serwera aplikacji, aby sprawdzić, czy wystąpiły jakiekolwiek nietypowe zdarzenia
- Sprawdź dziennik zdarzeń po stronie serwera aplikacji, aby sprawdzić, czy serwer aplikacji został uruchomiony ponownie
- 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 spowodować nieprawidłowe użycie 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, które znajdują się 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.
Główna przyczyna
Połączenie klienta usługi SignalR nigdy nie jest wywoływane DisposeAsync
, a 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 wzrasta w metrykach. Wszystkie te połączenia upuszczają się dopiero po ponownym uruchomieniu usługi Azure Function lub Azure SignalR. To zachowanie występuje, ponieważ funkcja platformy Azure ustanawia jedno połączenie klienta dla każdego żądania, a jeśli nie zatrzymasz połączenia klienta w metodzie funkcji, klient utrzymuje połączenia aktywne z usługą Azure SignalR Service.
Rozwiązanie
- Pamiętaj, aby zamknąć połączenie klienta, jeśli używasz klientów usługi SignalR w funkcji platformy Azure lub użyj klienta usługi SignalR jako pojedynczego.
- Zamiast używać klientów SignalR w funkcji platformy Azure, można tworzyć klientów usługi SignalR w dowolnym miejscu i używać powiązań usługi Azure Functions dla usługi Azure SignalR Service w celu negocjowania klienta z usługą Azure SignalR. Można również użyć powiązania do wysyłania komunikatów. Przykłady do negocjowania klienta i wysyłania komunikatów można znaleźć tutaj. Więcej informacji można znaleźć tutaj.
- W przypadku korzystania z klientów usługi SignalR w funkcji platformy Azure może istnieć lepsza architektura dla danego scenariusza. Sprawdź, czy projektujesz odpowiednią architekturę bezserwerową. Możesz odwołać się do aplikacji bezserwerowych czasu rzeczywistego za pomocą powiązań usługi SignalR Service w usłudze Azure Functions.
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 zamyka wszystkie obsługiwane przez niego połączenia klienckie.
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 przerwy 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 SignalR Service).
Wysokie użycie procesora CPU lub głodowanie puli wątków po stronie serwera może spowodować przekroczenie limitu czasu ping.
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 w metodach asynchronicznych asynchronizuj synchronizację lub przez Task.Result
/Task.Wait()
przyczynę tego scenariusza.
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
: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 serwera z powodu przekroczenia limitu czasu 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
- Otwórz dziennik po stronie serwera aplikacji, aby sprawdzić, czy wystąpiły jakiekolwiek nietypowe zdarzenia.
- Sprawdź dziennik zdarzeń po stronie serwera aplikacji, aby sprawdzić, czy serwer aplikacji został uruchomiony ponownie.
- 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 F5 w celu przechwycenia sieci od samego początku.
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.
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.