Partager via


Problèmes de performances lorsque vous effectuez des appels à des services web à partir d’une application ASP.NET

Cet article fournit de l’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 du produit d’origine : ASP.NET
Numéro de la base de connaissances d’origine : 821268

Symptômes

Lorsque vous effectuez des appels aux services web à partir d’une application ASP.NET, vous pouvez rencontrer des conflits, des performances médiocres et des blocages. Les clients peuvent signaler que les demandes arrêtent de répondre ou prennent beaucoup de temps pour s’exécuter. Si un blocage est soupçonné, 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) : délai d’expiration de la requête ».

Note

Cet article s’applique également aux applications qui effectuent HttpWebRequest des demandes directement.

Cause

Ce problème peut se produire, car ASP.NET limite le nombre de threads de travail et de threads de port d’achèvement qu’un appel peut utiliser pour exécuter des requêtes.

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 d’achèvement pour recevoir le rappel du service web. Toutefois, si la requête est redirigée ou nécessite une authentification, l’appel peut utiliser autant que deux threads de travail et deux threads de port d’achèvement. Par conséquent, vous pouvez épuiser la gestion ThreadPool lorsque plusieurs appels de service web se produisent en même temps.

Par exemple, supposons que le ThreadPool thread de travail est limité à 10 threads de travail et que tous les 10 threads de travail exécutent actuellement du code qui attend l’exécution d’un rappel. Le rappel ne peut jamais s’exécuter, car tous les éléments de travail qui sont mis en file d’attente jusqu’à ThreadPool ce qu’un thread soit disponible.

Une autre source potentielle de contention 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 tentent d’effectuer de nombreuses requêtes à une seule adresse IP en même temps, les threads peuvent devoir 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 pour mieux répondre à 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 appDomains utilisés.

Note

La recommandation de limiter le nombre de requêtes 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 d’achèvement 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 threads de port d’achèvement qui doivent être disponibles pour démarrer une demande distante ou une requête locale :

<httpRuntime minFreeThreads="8" minLocalRequestFreeThreads="8">

S’il n’y a pas suffisamment de threads disponibles, la requête est mise en file d’attente jusqu’à ce que les threads suffisants soient libres d’effectuer la requête. Par conséquent, ASP.NET n’exécutera pas plus que le nombre de requêtes suivant en même temps :

(maxWorkerThreads * nombre de processeurs) - minFreeThreads

Note

Le minFreeThreads paramètre et le minLocalRequestFreeThreads paramètre ne sont pas multipliés implicitement 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 à un débit beaucoup plus rapide que les threads de travail créés à partir des fonctionnalités de paramétrage des threads par défaut du Common Language Runtime (CLR).

Ce paramètre permet d’ASP.NET de traiter les demandes susceptibles de remplir soudainement la file d’attente de requêtes ASP.NET en raison d’un ralentissement sur un serveur principal, d’une rafale soudaine de requêtes à partir de la fin du client ou d’une augmentation soudaine du nombre de requêtes 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 pas présent dans le fichier Web.config ou dans le fichier Machine.config . Ce paramètre est implicitement multiplié par le nombre de processeurs.

Maxconnection

Le maxconnection paramètre détermine le nombre de connexions à 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 abordés précédemment dans cet article sont tous au niveau du processus. Toutefois, le maxconnection paramètre de paramètre s’applique 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 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é.

Note

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 du maxIoThreads paramètre sur 100.
  • Définissez la valeur du maxconnection paramètre sur 12*N (où N correspond au nombre de processeurs dont vous disposez).
  • Définissez les valeurs du minFreeThreads paramètre sur 88*N et le minLocalRequestFreeThreads paramètre sur 76*N.
  • Définissez la valeur sur minWorkerThreads 50. N’oubliez pas que minWorkerThreads le fichier de configuration 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 vous avez activé l’hyperthreading, vous devez utiliser le nombre de processeurs logiques au lieu du nombre de processeurs physiques. Par exemple, si vous avez un serveur à quatre processeurs avec hyperthreading activé, la valeur de N dans les formules est 8 au lieu de 4.

Note

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 d’achèvement sont disponibles pour d’autres utilisations (comme pour les rappels de service web).

Par exemple, vous disposez d’un serveur avec quatre processeurs et hyperthreading activés. 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 par 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 celles-ci ThreadPool ne sont pas épuisées :

  • Le site web héberge une seule application (AppDomain).
  • Chaque demande d’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 options ci-dessous utilisent probablement trop de connexions :

  • Les demandes sont adressées à plusieurs adresses IP.
  • Les demandes sont redirigées (code d’état 302).
  • 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 les 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 contentions médiocres sur IIS avec ASP.NET, accédez aux blogs Microsoft suivants :