Guide de dépannage pour résoudre des problèmes courants rencontrés avec Azure SignalR Service
Cet article fournit des conseils de résolution des problèmes pour certains problèmes courants rencontrés par les clients.
Jeton d’accès trop long
Erreurs possibles
ERR_CONNECTION_
côté client- 414 URI trop long
- 413 Payload Too Large
- La longueur du jeton d’accès ne doit pas dépasser 4 Ko. 413 Entité de demande trop grande
Origine
Pour HTTP/2, la longueur maximale d’un en-tête est de 4 K. Par conséquent, si vous utilisez un navigateur pour accéder au service Azure, cette limitation génère une erreur ERR_CONNECTION_
.
Pour les clients HTTP/1.1 ou C#, la longueur maximale de l’URI est de 12 K et la longueur maximale de l’en-tête est de 16 K.
Avec le kit de développement logiciel (SDK) version 1.0.6 ou supérieure, /negotiate
lève 413 Payload Too Large
quand le jeton d’accès généré est d’une longueur supérieure à 4 K.
Solution
Par défaut, les revendications de context.User.Claims
sont incluses lors de la génération du jeton d’accès JWT pour ASRS(Azure SignalR Service). Ainsi, les revendications sont conservées et peuvent être transmises d’ASRS au Hub
lorsque le client se connecte au Hub
.
Dans certains cas, des revendications context.User.Claims
sont utilisées pour stocker de grandes quantités d’informations pour le serveur d’applications, dont la plupart ne sont pas utilisées par les Hub
s mais par d’autres composants.
Le jeton d’accès généré est transmis via le réseau et, pour les connexions WebSocket/SSE, les jetons d’accès sont transmis via des chaînes de requête. C’est pourquoi nous recommandons de transmettre les revendications nécessaires du client via ASRS à votre serveur d’applications quand le Hub en a besoin.
ClaimsProvider
vous permet de personnaliser les revendications transmises à ASRS dans le jeton d’accès.
Pour ASP.NET Core :
services.AddSignalR()
.AddAzureSignalR(options =>
{
// pick up necessary claims
options.ClaimsProvider = context => context.User.Claims.Where(...);
});
Pour ASP.NET :
services.MapAzureSignalR(GetType().FullName, options =>
{
// pick up necessary claims
options.ClaimsProvider = context.Authentication?.User.Claims.Where(...);
});
Vous avez des problèmes ou des commentaires sur la résolution des problèmes ? Faites-le nous savoir.
TLS 1.2 requis
Erreurs possibles
- ASP.NET « Aucun serveur disponible » erreur #279
- Erreur #324« La connexion n’est pas active. Impossible d’envoyer des données au service. » ASP.NET
- « Une erreur s’est produite lors de l’envoi de la requête HTTP à
https://<API endpoint>
. Cette erreur peut se produire si le certificat de serveur n’est pas correctement configuré avec HTTP.SYS dans le cas HTTPS. La cause possible de cette erreur est une incompatibilité de la liaison de sécurité entre le client et le serveur. »
Origine
Le service Azure prend uniquement en charge le protocole TLS 1.2 pour les problèmes de sécurité. Avec .NET Framework, il est possible que le protocole par défaut ne soit pas TLS 1.2. Par conséquent, les connexions du serveur à ASRS ne peuvent pas être établies.
Guide de résolution des problèmes
Si cette erreur peut être reproduite localement, désactivez l’option Uniquement mon code et levez toutes les exceptions CLR, puis déboguez le serveur d’applications localement pour voir les levées d’exceptions.
Désactive l’option Uniquement mon code
Lever des exceptions CLR
Consultez la levée d’exceptions lors du débogage du code côté serveur d’applications :
Pour les exceptions ASP.NET, vous pouvez également ajouter le code suivant à votre
Startup.cs
pour activer la trace détaillée et voir les erreurs du journal.app.MapAzureSignalR(this.GetType().FullName); // Make sure this switch is called after MapAzureSignalR GlobalHost.TraceManager.Switch.Level = SourceLevels.Information;
Solution
Ajoutez le code suivant à votre démarrage :
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Vous avez des problèmes ou des commentaires sur la résolution des problèmes ? Faites-le nous savoir.
400 Requête incorrecte retournée aux demandes du client
Origine
Vérifiez si la demande de votre client comporte plusieurs chaînes de requête hub
. hub
est un paramètre de requête préservé et si le service détecte plus d’un hub
dans la requête, il renvoie l’erreur 400.
Vous avez des problèmes ou des commentaires sur la résolution des problèmes ? Faites-le nous savoir.
Code 401 - Non autorisé retourné pour les demandes des clients
Origine
Actuellement, la valeur par défaut de la durée de vie du jeton JWT est d’une heure (1).
OK pour ASP.NET Core SignalR avec le type de transport WebSocket.
Pour un autre type de transport, un SSE et une interrogation longue d’ASP.NET Core SignalR, cette durée de vie par défaut signifie que la connexion peut persister par défaut une heure maximum.
Pour ASP.NET SignalR, le client envoie une demande « keep alive » /ping
au service de temps en temps. Quand le /ping
échoue, le client abandonne la connexion et ne se reconnecte jamais. Pour ASP.NET SignalR, la durée de vie du jeton par défaut fait durer la connexion au maximum pendant une heure pour tous les types de transport.
Solution
Par souci de sécurité, il n’est pas recommandé d’étendre le protocole TTL. Nous vous suggérons d’ajouter une logique de reconnexion à partir du client pour redémarrer la connexion quand une telle erreur 401 se produit. Lorsque le client redémarre la connexion, il négocie avec le serveur d’applications pour obtenir à nouveau le jeton JWT et un jeton renouvelé.
Pour savoir comment redémarrer des connexions client, voir ici.
Vous avez des problèmes ou des commentaires sur la résolution des problèmes ? Faites-le nous savoir.
Code 404 retourné pour les demandes des clients
Une connexion persistante SignalR commence par négocier (/negotiate
) l’accès au Azure SignalR Service, puis établit la connexion réelle à Azure SignalR Service.
Guide de résolution des problèmes
- Voici Comment afficher des demandes sortantes pour obtenir la demande du client au service.
- Vérifiez l’URL de la demande quand l’erreur 404 se produit. Si l’URL cible votre application web, et est similaire à
{your_web_app}/hubs/{hubName}
, vérifiez si la valeur deSkipNegotiation
du client esttrue
. Le client reçoit l’URL de redirection quand il négocie pour la première fois avec le serveur d’applications. Le client ne doit pas ignorer la négociation lors de l’utilisation d’Azure SignalR. - Une autre erreur 404 peut se produire quand la demande de connexion est traitée plus de cinq (5) secondes après l’appel de
/negotiate
. Vérifiez l’horodatage de la demande client, puis ouvrez un problème chez nous si la réponse à la demande adressée au service est lente.
Vous avez des problèmes ou des commentaires sur la résolution des problèmes ? Faites-le nous savoir.
Erreur 404 retournée pour la demande de reconnexion d’ASP.NET SignalR
Pour ASP.NET SignalR, en cas d’interruption de la connexion client, celle-ci est rétablie à l’aide du même connectionId
à trois reprises avant son arrêt. Le commande /reconnect
peut être utile si la connexion est interrompue en raison de problèmes intermittents du réseau et que la commande /reconnect
peut rétablir correctement la connexion persistante. Dans d’autres circonstances, par exemple, si la connexion client est interrompue en raison de la perte de la connexion serveur routée, ou parce que le service SignalR rencontre des erreurs internes telles qu’un redémarrage, un basculement ou un déploiement d’instance. La connexion n’existe plus, donc /reconnect
retourne 404
. Il s’agit du comportement attendu de la commande /reconnect
. Après trois nouvelles tentatives, la connexion s’arrête. Nous vous suggérons de vous doter d’une logique de redémarrage de connexion lorsque la connexion s’arrête.
Vous avez des problèmes ou des commentaires sur la résolution des problèmes ? Faites-le nous savoir.
Erreur 429 (Trop de demandes) retournée aux demandes client
Il existe deux cas.
Le nombre de connexions simultanées dépasse la limite
Pour des instances Gratuites, la limite du nombre de connexions simultanées est de 20. Pour des instances Standard, la limite du nombre de connexions simultanées par unité est de 1 K, ce qui signifie que Unit100 autorise 100 000 connexions simultanées.
Les connexions incluent les connexions client et serveur. Pour savoir comment les connexions sont comptées, consultez ceci.
NegotiateThrottled
Lorsque trop de clients négocient des demandes en même temps, cela peut être limité. La limite est liée au nombre d’unités dont plus d’unités ont une limite plus élevée. En outre, nous vous suggérons d’avoir un délai aléatoire avant de vous reconnecter. Consultez ceci pour les exemples de nouvelles tentatives.
Vous avez des problèmes ou des commentaires sur la résolution des problèmes ? Faites-le nous savoir.
500 Erreur lors de la négociation : Azure SignalR Service n’est pas encore connecté. Réessayez plus tard.
Origine
Cette erreur est signalée quand il n’existe aucune connexion serveur à Azure SignalR Service.
Guide de résolution des problèmes
Activez la trace côté serveur pour connaître les détails de l’erreur lorsque le serveur tente de se connecter à Azure SignalR Service.
Activer la journalisation côté serveur pour ASP.NET Core SignalR
La journalisation côté serveur pour ASP.NET Core SignalR s’intègre avec la journalisation basée sur ILogger
fournie dans le framework ASP.NET Core. Vous pouvez activer la journalisation côté serveur à l’aide de ConfigureLogging
, un exemple d’utilisation comme suit :
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConsole();
logging.AddDebug();
})
Les catégories d’enregistreur d’événements pour Azure SignalR commencent toujours par Microsoft.Azure.SignalR
. Pour activer les journaux détaillés d’Azure SignalR, configurez les préfixes précédents sur le niveau Debug
dans votre fichier appsettings.json, et consultez l’exemple suivant :
{
"Logging": {
"LogLevel": {
...
"Microsoft.Azure.SignalR": "Debug",
...
}
}
}
Activer les traces côté serveur pour ASP.NET SignalR
En cas d’utilisation d’une version du Kit de développement logiciel (SDK) >= 1.0.0
, vous pouvez activer les traces en ajoutant le code suivant au fichier web.config
: (Détails).
<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>
Vous avez des problèmes ou des commentaires sur la résolution des problèmes ? Faites-le nous savoir.
Pertes de connexion client
Lorsque le client est connecté à Azure SignalR, la connexion persistante entre le client et Azure SignalR peut parfois s’interrompre pour différentes raisons. Cette section décrit plusieurs causes possibles d’une telle perte de connexion et fournit des conseils sur la façon d’identifier la cause racine.
Erreurs possibles côté 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."}
Origine
Les connexions client peuvent être interrompues dans diverses circonstances :
- Quand
Hub
lève des exceptions avec la demande entrante - Quand la connexion serveur vers laquelle le client est routé s’interrompt, consultez la section suivante pour plus de détails sur les pertes de connexion serveur
- Quand un problème de connectivité réseau se produit entre le client et SignalR Service
- Quand SignalR Service rencontre des erreurs internes, par exemple de redémarrage, de basculement ou de déploiement d’instance, etc.
Guide de résolution des problèmes
- Ouvrez le journal côté serveur d’applications pour voir si quelque chose d’anormal s’est produit.
- Vérifiez le journal des événements côté serveur d’applications pour voir si le serveur d’applications a redémarré.
- Ouvrez un problème chez nous en fournissant le laps de temps, et envoyez-nous par e-mail le nom de la ressource.
Vous avez des problèmes ou des commentaires sur la résolution des problèmes ? Faites-le nous savoir.
La connexion client augmente constamment
Une utilisation incorrecte de la connexion cliente peut en être la cause. Si quelqu’un oublie d’arrêter ou de supprimer le client SignalR, la connexion reste ouverte.
Erreurs possibles observées dans les métriques de SignalR de la section Surveillance du menu des ressources du portail Azure
Les connexions client augmentent constamment pendant une longue période dans les métriques d’Azure SignalR.
Origine
La commande DisposeAsync
de la connexion client SignalR n’est jamais appelée et la connexion reste ouverte.
Guide de résolution des problèmes
Vérifiez si le client SignalR ne se ferme jamais.
Solution
Vérifiez si vous fermez la connexion. Appelez manuellement la commande HubConnection.DisposeAsync()
pour arrêter la connexion après l’avoir utilisée.
Par exemple :
var connection = new HubConnectionBuilder()
.WithUrl(...)
.Build();
try
{
await connection.StartAsync();
// Do your stuff
await connection.StopAsync();
}
finally
{
await connection.DisposeAsync();
}
Utilisation incorrecte courante de la connexion client
Exemple de fonction Azure
Ce problème se produit souvent quand un utilisateur établit une connexion client SignalR dans une méthode de fonction Azure au lieu d’en faire un membre statique de la classe de fonction. Vous vous attendez peut-être à ce qu’une seule connexion client soit établie, mais vous constatez au contraire que le nombre de connexions client augmente constamment dans les métriques. Toutes ces connexions sont annulées uniquement après le redémarrage de la fonction Azure ou du service Azure SignalR. Cela est dû au fait que la fonction Azure crée une connexion client pour chaque demande. Si vous n’arrêtez pas la connexion client dans la méthode de fonction, le client conserve les connexions actives au service Azure SignalR.
Solution
- N’oubliez pas de fermer la connexion client si vous utilisez des clients SignalR dans une fonction Azure ou si vous utilisez un client SignalR en tant que singleton.
- Au lieu d’utiliser des clients SignalR dans une fonction Azure, vous pouvez créer des clients SignalR partout ailleurs et utiliser des Liaisons Azure Functions pour Azure SignalR Service afin de négocier l’accès du client à Azure SignalR. Vous pouvez également utiliser la liaison pour envoyer des messages. Vous trouverez des exemples pour négocier l’accès du client et envoyer des messages ici. Des informations supplémentaires sont disponibles ici.
- Lorsque vous utilisez des clients SignalR dans une fonction Azure Function, il peut y avoir une meilleure architecture à votre scénario. Vérifiez si vous concevez une architecture sans serveur appropriée. Vous pouvez vous référer à Applications sans serveur en temps réel avec les liaisons SignalR Service dans Azure Functions.
Vous avez des problèmes ou des commentaires sur la résolution des problèmes ? Faites-le nous savoir.
Pertes de connexion serveur
Au démarrage du serveur d’applications, en arrière-plan, le Kit de développement logiciel (SDK) Azure commence à initier des connexions serveur à l’Azure SignalR distant. Comme décrit dans Éléments internes d’Azure SignalR Service, Azure SignalR achemine les trafics clients entrants vers ces connexions serveur. Lorsqu’une connexion de serveur est supprimée, elle ferme toutes les connexions client qu’elle servait.
Les connexions entre le serveur d’applications et SignalR Service étant persistantes, elles peuvent rencontrer des problèmes de connectivité réseau. Dans le kit SDK Serveur, nous avons une stratégie Toujours se reconnecter pour les connexions serveur. La meilleure pratique consiste à ajouter une logique de reconnexion continue aux clients avec un délai aléatoire afin d’éviter l’envoi d’une quantité massive de demandes simultanées au serveur.
De nouvelles versions d’Azure SignalR Service sont publiées régulièrement, ainsi que des mises à jour correctives ou des mises à niveau à l’échelle d’Azure, qui interrompent occasionnellement nos services dépendants. Ces événements peuvent entraîner une courte interruption des services. Toutefois, tant que le mécanisme de déconnexion/reconnexion fonctionne côté client, l’effet est minime, comme toute déconnexion/reconnexion côté client.
Cette section décrit plusieurs causes possibles de perte de connexion serveur, et fournit des conseils sur la façon d’identifier la cause racine.
Erreurs possibles côté serveur
[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.
Origine
La connexion serveur-service est fermée par ASRS(Azure SignalR Service).
Une utilisation élevée du processeur ou une insuffisance du pool de threads côté serveur peuvent entraîner un délai d’expiration du test ping.
Pour SignalR ASP.NET, un problème connu a été résolu dans le Kit de développement logiciel (SDK) 1.6.0. Mettez à niveau votre Kit de développement logiciel (SDK) vers la version la plus récente.
Insuffisance du pool de threads
Si votre serveur rencontre une insuffisance, cela signifie qu’aucun thread ne traite de messages. Tous les threads ne répondent pas dans une certaine méthode.
Normalement, dans les méthodes asynchrones, asynchrones sur synchrone ou par Task.Result
/Task.Wait()
provoque ce scénario.
Consultez Meilleures pratiques d’ASP.NET Core en matière de performances.
Apprenez-en davantage sur l’insuffisance du pool de threads.
Comment détecter une insuffisance du pool de threads
Vérifiez le nombre de threads. S’il n’y a pas de pics à ce stade, effectuez les étapes suivantes :
Si vous utilisez Azure App Service, vérifiez le nombre de threads dans les métriques. Vérifiez l’agrégation
Max
:Si vous utilisez .NET Framework, vous pouvez trouver des métriques dans l’Analyseur de performances de votre machine virtuelle serveur.
Si vous utilisez .NET Core dans un conteneur, consultez Collecter les diagnostics dans des conteneurs.
Vous pouvez également utiliser du code pour détecter une insuffisance du 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://zcusa.951200.xyz/dotnet/framework/performance/thread-pool-etw-events#threadpoolworkerthreadadjustmentadjustment
if (eventData.EventId == EventIdForThreadPoolWorkerThreadAdjustmentAdjustment &&
eventData.Payload[2] as uint? == ReasonForStarvation)
{
_logger.LogWarning("Thread pool starvation detected!");
}
}
}
Ajoutez-le à votre service :
service.AddSingleton<ThreadPoolStarvationDetector>();
Ensuite, vérifiez votre journal lorsque le serveur s’est déconnecté en raison du délai d’expiration du test ping.
Comment trouver la cause racine de l’insuffisance du pool de threads
Pour trouver la cause racine de l’insuffisance du pool de threads :
- Videz la mémoire, puis analysez la pile des appels. Pour plus d’informations, consultez Collecter et analyser les vidages de mémoire.
- Utilisez clrmd pour vider la mémoire lorsque l’insuffisance du pool de threads est détectée. Consignez ensuite la pile des appels.
Guide de résolution des problèmes
- Ouvrez le journal côté serveur d’applications pour voir si quelque chose d’anormal s’est produit.
- Vérifiez le journal des événements côté serveur d’applications pour voir si le serveur d’applications a redémarré.
- Créez un problème. Fournissez le laps de temps et envoyez-nous par e-mail le nom de la ressource.
Vous avez des problèmes ou des commentaires sur la résolution des problèmes ? Faites-le nous savoir.
Conseils
Comment afficher la demande sortante du client ?
Prenons ASP.NET Core par exemple (ASP.NET est similaire) :
Dans le navigateur : Prenons l’exemple de Chrome. Vous pouvez utiliser la touche F12 pour ouvrir la fenêtre de console, puis passer à l’onglet Réseau. Vous devrez peut-être actualiser la page à l’aide de F5 pour capturer le réseau depuis le tout début.
À partir d’un client C# :
Vous pouvez afficher les trafics web locaux à l’aide de Fiddler. Les trafics WebSocket sont pris en charge depuis Fiddler version 4.5.
Comment redémarrer une connexion client ?
Voici les exemples de code contenant une logique de redémarrage de connexion avec une stratégie TOUJOURS RÉESSAYER :
Vous avez des problèmes ou des commentaires sur la résolution des problèmes ? Faites-le nous savoir.
Étapes suivantes
Dans ce guide, vous avez appris à gérer les problèmes courants. Vous avez également découvert d’autres méthodes de dépannage génériques.