Problèmes de performances lorsque vous effectuez des appels à des services web à partir d’une application ASP.NET
Cet article fournit une aide pour résoudre les problèmes de performances qui se produisent lorsque vous effectuez des appels à des services web à partir d’une application Microsoft ASP.NET.
Version d’origine du produit : ASP.NET
Numéro de la base de connaissances d’origine : 821268
Symptômes
Lorsque vous effectuez des appels à des services web à partir d’une application ASP.NET, vous pouvez rencontrer des conflits, des performances médiocres et des interblocages. Les clients peuvent signaler que les demandes cessent de répondre ou prennent beaucoup de temps à s’exécuter. En cas de suspicion d’interblocage, le processus de travail peut être recyclé.
Vous pouvez recevoir le message d’erreur d’exception suivant lorsque vous effectuez un appel à la HttpWebRequest.GetResponse
méthode :
« System.InvalidOperationException : il n’y avait pas assez de threads libres dans l’objet ThreadPool pour terminer l’opération. »
Vous pouvez également recevoir le message d’erreur d’exception suivant dans le navigateur :
« HttpException (0x80004005) : la demande a expiré. »
Remarque
Cet article s’applique également aux applications qui effectuent directement des HttpWebRequest
demandes.
Cause
Ce problème peut se produire car ASP.NET limite le nombre de threads de travail et de ports de saisie semi-automatique qu’un appel peut utiliser pour exécuter des demandes.
En règle générale, un appel à un service web utilise un thread de travail pour exécuter le code qui envoie la requête et un thread de port de saisie semi-automatique pour recevoir le rappel du service web. Toutefois, si la requête est redirigée ou nécessite une authentification, l’appel peut utiliser jusqu’à deux threads de travail et deux threads de port de saisie semi-automatique. Par conséquent, vous pouvez épuiser le managé ThreadPool
lorsque plusieurs appels de service web se produisent en même temps.
Par exemple, supposons que le ThreadPool
est limité à 10 threads de travail et que les 10 threads de travail exécutent actuellement du code qui attend qu’un rappel s’exécute. Le rappel ne peut jamais s’exécuter, car tous les éléments de travail qui sont mis en file d’attente vers le ThreadPool
sont bloqués jusqu’à ce qu’un thread soit disponible.
Une autre source potentielle de conflit est le maxconnection
paramètre que l’espace System.Net
de noms utilise pour limiter le nombre de connexions. En règle générale, cette limite fonctionne comme prévu. Toutefois, si de nombreuses applications essaient d’effectuer plusieurs requêtes à une seule adresse IP en même temps, les threads peuvent avoir à attendre une connexion disponible.
Résolution
Pour résoudre ces problèmes, vous pouvez paramétrer les paramètres suivants dans le fichier Machine.config en fonction de votre situation :
maxWorkerThreads
minWorkerThreads
maxIoThreads
minFreeThreads
minLocalRequestFreeThreads
maxconnection
executionTimeout
Pour résoudre ces problèmes, effectuez les actions suivantes :
- Limitez le nombre de requêtes ASP.NET qui peuvent s’exécuter en même temps à environ 12 par processeur.
- Autoriser les rappels de service web à utiliser librement des threads dans le
ThreadPool
. - Sélectionnez une valeur appropriée pour le
maxconnections
paramètre . Basez votre sélection sur le nombre d’adresses IP et de domaines d’application utilisés.
Remarque
La recommandation de limiter le nombre de demandes de ASP.NET à 12 par processeur est un peu arbitraire. Toutefois, cette limite s’est avérée efficace pour la plupart des applications.
MaxWorkerThreads et maxIoThreads
ASP.NET utilise les deux paramètres de configuration suivants pour limiter le nombre maximal de threads de travail et de threads de saisie semi-automatique utilisés :
<processModel maxWorkerThreads="20" maxIoThreads="20">
Le maxWorkerThreads
paramètre et le maxIoThreads
paramètre sont implicitement multipliés par le nombre de processeurs. Par exemple, si vous avez deux processeurs, le nombre maximal de threads de travail est de 2 * maxWorkerThreads
.
MinFreeThreads et minLocalRequestFreeThreads
ASP.NET contient également les paramètres de configuration suivants qui déterminent le nombre de threads de travail et de ports d’achèvement qui doivent être disponibles pour démarrer une demande distante ou une demande locale :
<httpRuntime minFreeThreads="8" minLocalRequestFreeThreads="8">
S’il n’y a pas suffisamment de threads disponibles, la demande est mise en file d’attente jusqu’à ce que suffisamment de threads soient libres d’effectuer la requête. Par conséquent, ASP.NET n’exécutez pas plus que le nombre de requêtes suivant en même temps :
(maxWorkerThreads
* nombre d’uc) - minFreeThreads
Remarque
Le minFreeThreads
paramètre et le minLocalRequestFreeThreads
paramètre ne sont pas implicitement multipliés par le nombre de processeurs.
MinWorkerThreads
ASP.NET contient également le paramètre de configuration suivant qui détermine le nombre de threads de travail qui peuvent être mis à disposition immédiatement pour traiter une demande distante.
<processModel minWorkerThreads="1">
Les threads contrôlés par ce paramètre peuvent être créés beaucoup plus rapidement que les threads de travail créés à partir des fonctionnalités de réglage des threads par défaut du Common Language Runtime (CLR).
Ce paramètre permet ASP.NET de traiter les demandes qui peuvent soudainement remplir la file d’attente des demandes ASP.NET en raison d’un ralentissement sur un serveur principal, d’une rafale soudaine de requêtes de l’extrémité du client ou d’un problème similaire qui entraînerait une augmentation soudaine du nombre de demandes dans la file d’attente.
La valeur par défaut du minWorkerThreads
paramètre est 1. Nous vous recommandons de définir la valeur du minWorkerThreads
paramètre sur la valeur suivante :
minWorkerThreads
= maxWorkerThreads
/ 2
Par défaut, le minWorkerThreads
paramètre n’est présent ni dans le fichier Web.config ni dans le fichier Machine.config . Ce paramètre est implicitement multiplié par le nombre d’uc.
Maxconnection
Le maxconnection
paramètre détermine le nombre de connexions qui peuvent être établies à une adresse IP spécifique. Le paramètre apparaît comme suit :
<connectionManagement>
<add address="*" maxconnection="2">
<add address="http://65.53.32.230" maxconnection="12">
</connectionManagement>
Si le code de l’application fait référence à l’application par nom d’hôte au lieu de l’adresse IP, le paramètre doit apparaître comme suit :
<connectionManagement>
<add address="*" maxconnection="2">
<add address="http://hostname" maxconnection="12">
</connectionManagement>
Enfin, si l’application est hébergée sur un port autre que 80, le paramètre doit inclure le port non standard dans l’URL, comme ci-dessous :
<connectionManagement>
<add address="*" maxconnection="2">
<add address="http://hostname:8080" maxconnection="12">
</connectionManagement>
Les paramètres des paramètres décrits plus haut dans cet article sont tous au niveau du processus. Toutefois, le paramètre s’applique maxconnection
au niveau AppDomain. Par défaut, étant donné que ce paramètre s’applique au niveau AppDomain, vous pouvez créer un maximum de deux connexions à une adresse IP spécifique à partir de chaque AppDomain dans votre processus.
ExecutionTimeout
ASP.NET utilise le paramètre de configuration suivant pour limiter le temps d’exécution de la requête :
<httpRuntime executionTimeout="90"/>
Vous pouvez également définir cette limite à l’aide de la Server.ScriptTimeout
propriété .
Remarque
Si vous augmentez la valeur du executionTimeout
paramètre, vous devrez peut-être également modifier le processModel
responseDeadlockInterval
paramètre.
Recommandations
Les paramètres recommandés dans cette section peuvent ne pas fonctionner pour toutes les applications. Toutefois, les informations supplémentaires suivantes peuvent vous aider à effectuer les ajustements appropriés.
Si vous effectuez un appel de service web à une seule adresse IP à partir de chaque page ASPX, Microsoft vous recommande d’utiliser les paramètres de configuration suivants :
- Définissez les valeurs du
maxWorkerThreads
paramètre et dumaxIoThreads
paramètre sur 100. - Définissez la valeur du paramètre sur
maxconnection
12*N (où N est le nombre de processeurs dont vous disposez). - Définissez les valeurs du paramètre sur
minFreeThreads
88*N et leminLocalRequestFreeThreads
paramètre sur 76*N. - Définissez la valeur de
minWorkerThreads
sur 50. N’oubliez pas queminWorkerThreads
n’est pas dans le fichier de configuration par défaut. Vous devez l’ajouter.
Certaines de ces recommandations impliquent une formule simple qui implique le nombre de processeurs sur un serveur. La variable qui représente le nombre d’UC dans les formules est N.
Pour ces paramètres, si l’hyperthreading est activé, vous devez utiliser le nombre d’uc logiques au lieu du nombre de processeurs physiques. Par exemple, si vous avez un serveur à quatre processeurs avec l’hyperthreading activé, la valeur de N dans les formules est 8 au lieu de 4.
Remarque
Lorsque vous utilisez cette configuration, vous pouvez exécuter un maximum de 12 requêtes ASP.NET par processeur en même temps, car 100-88=12. Par conséquent, au moins 88*N threads de travail et 88*N threads de port de saisie semi-automatique sont disponibles pour d’autres utilisations (par exemple, pour les rappels de service web).
Par exemple, vous disposez d’un serveur avec quatre processeurs et l’hyperthreading activé. En fonction de ces formules, vous devez utiliser les valeurs suivantes pour les paramètres de configuration mentionnés dans cet article.
<system.web>
<processModel maxWorkerThreads="100" maxIoThreads="100" minWorkerThreads="50"/>
<httpRuntime minFreeThreads="704" minLocalRequestFreeThreads="608"/>
</system.web>
<system.net>
<connectionManagement>
<add address="[ProvideIPHere]" maxconnection="96"/>
</connectionManagement>
</system.net>
En outre, lorsque vous utilisez cette configuration, 12 connexions sont disponibles par uc et adresse IP pour chaque AppDomain. Par conséquent, dans le scénario suivant, très peu de contention se produit lorsque les requêtes attendent des connexions et que le ThreadPool
n’est pas épuisé :
- Le web héberge une seule application (AppDomain).
- Chaque demande pour une page ASPX effectue une demande de service web.
- Toutes les demandes sont adressées à la même adresse IP.
Toutefois, lorsque vous utilisez cette configuration, les scénarios qui impliquent l’une des connexions ci-dessous utilisent probablement trop de connexions :
- Les demandes concernent plusieurs adresses IP.
- Les requêtes sont redirigées (code 302 status).
- Les demandes nécessitent une authentification.
- Les requêtes sont effectuées à partir de plusieurs AppDomains.
Dans ces scénarios, il est judicieux d’utiliser une valeur inférieure pour le maxconnection
paramètre et des valeurs supérieures pour le minFreeThreads
paramètre et le minLocalRequestFreeThreads
paramètre.
Plus d’informations
Pour plus d’informations, consultez Amélioration des performances ASP.NET.
Si vous rencontrez des performances et des conflits médiocres sur IIS avec ASP.NET, consultez les blogs Microsoft suivants :
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultezEnvoyer et afficher des commentaires pour