Prestatieproblemen wanneer u webservices aanroept vanuit een ASP.NET-toepassing

Dit artikel biedt hulp bij het oplossen van prestatieproblemen die optreden wanneer u webservices aanroept vanuit een Microsoft ASP.NET-toepassing.

Oorspronkelijke productversie: ASP.NET
Origineel KB-nummer: 821268

Symptomen

Wanneer u webservices aanroept vanuit een ASP.NET-toepassing, kunnen er conflicten, slechte prestaties en impasses optreden. Clients kunnen melden dat aanvragen niet meer reageren of dat het lang duurt om uit te voeren. Als er een impasse wordt vermoed, kan het werkproces worden gerecycled.

Mogelijk wordt het volgende uitzonderingsfoutbericht weergegeven wanneer u de methode aanroept HttpWebRequest.GetResponse :

"System.InvalidOperationException: er waren onvoldoende vrije threads in het ThreadPool-object om de bewerking te voltooien."

Mogelijk ontvangt u ook het volgende uitzonderingsfoutbericht in de browser:

"HttpException (0x80004005): Time-out van aanvraag."

Opmerking

Dit artikel is ook van toepassing op toepassingen die rechtstreeks aanvragen indienen HttpWebRequest .

Oorzaak

Dit probleem kan optreden omdat ASP.NET het aantal werkerthreads en voltooiingspoortthreads beperkt dat een aanroep kan gebruiken om aanvragen uit te voeren.

Normaal gesproken gebruikt een aanroep naar een webservice één werkrolthread om de code uit te voeren waarmee de aanvraag wordt verzonden en één voltooiingspoortthread om de callback van de webservice te ontvangen. Als de aanvraag echter wordt omgeleid of verificatie is vereist, kan de aanroep maar liefst twee werkrolthreads en twee voltooiingspoortthreads gebruiken. U kunt het beheerde ThreadPool dus uitputten wanneer er meerdere webserviceaanroepen tegelijk plaatsvinden.

Stel dat de ThreadPool is beperkt tot 10 werkthreads en dat alle 10 werkthreads momenteel code uitvoeren die wacht op het uitvoeren van een callback. De callback kan nooit worden uitgevoerd, omdat werkitems die in de ThreadPool wachtrij staan, worden geblokkeerd totdat er een thread beschikbaar is.

Een andere mogelijke bron van conflicten is de maxconnection parameter die de System.Net naamruimte gebruikt om het aantal verbindingen te beperken. Over het algemeen werkt deze limiet zoals verwacht. Als veel toepassingen echter veel aanvragen tegelijk naar één IP-adres proberen te verzenden, moeten threads mogelijk wachten op een beschikbare verbinding.

Oplossing

Om deze problemen op te lossen, kunt u de volgende parameters in het Machine.config-bestand afstemmen op uw situatie:

  • maxWorkerThreads
  • minWorkerThreads
  • maxIoThreads
  • minFreeThreads
  • minLocalRequestFreeThreads
  • maxconnection
  • executionTimeout

Voer de volgende acties uit om deze problemen op te lossen:

  • Beperk het aantal ASP.NET aanvragen dat tegelijkertijd kan worden uitgevoerd tot ongeveer 12 per CPU.
  • Toestaan dat webservice-callbacks threads vrij gebruiken in de ThreadPool.
  • Selecteer een geschikte waarde voor de maxconnections parameter. Baseer uw selectie op het aantal IP-adressen en AppDomains dat wordt gebruikt.

Opmerking

De aanbeveling om het aantal ASP.NET aanvragen te beperken tot 12 per CPU is een beetje willekeurig. Deze limiet werkt echter goed voor de meeste toepassingen.

MaxWorkerThreads en maxIoThreads

ASP.NET gebruikt de volgende twee configuratie-instellingen om het maximum aantal werkrolthreads en voltooiingthreads te beperken dat wordt gebruikt:

<processModel maxWorkerThreads="20" maxIoThreads="20">

De maxWorkerThreads parameter en de maxIoThreads parameter worden impliciet vermenigvuldigd met het aantal CPU's. Als u bijvoorbeeld twee processors hebt, is het maximum aantal werkrolthreads 2 * maxWorkerThreads.

MinFreeThreads en minLocalRequestFreeThreads

ASP.NET bevat ook de volgende configuratie-instellingen die bepalen hoeveel werkrolthreads en voltooiingspoortthreads beschikbaar moeten zijn om een externe aanvraag of een lokale aanvraag te starten:

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

Als er onvoldoende threads beschikbaar zijn, wordt de aanvraag in de wachtrij geplaatst totdat voldoende threads vrij zijn om de aanvraag te doen. ASP.NET voert dus niet meer dan het volgende aantal aanvragen tegelijk uit:

(maxWorkerThreads * aantal CPU's) - minFreeThreads

Opmerking

De minFreeThreads parameter en de minLocalRequestFreeThreads parameter worden niet impliciet vermenigvuldigd met het aantal CPU's.

MinWorkerThreads

ASP.NET bevat ook de volgende configuratie-instelling waarmee wordt bepaald hoeveel werkrolthreads onmiddellijk beschikbaar kunnen worden gesteld voor het uitvoeren van een externe aanvraag.

<processModel minWorkerThreads="1">

Threads die door deze instelling worden beheerd, kunnen veel sneller worden gemaakt dan werkthreads die zijn gemaakt op basis van de standaardmogelijkheden voor thread-afstemming van Common Language Runtime (CLR).

Met deze instelling kunt u ASP.NET aanvragen verwerken die plotseling de wachtrij voor ASP.NET aanvragen vullen vanwege een vertraging op een back-endserver, een plotselinge burst van aanvragen van de clientzijde of iets dergelijks dat een plotselinge toename van het aantal aanvragen in de wachtrij zou veroorzaken.

De standaardwaarde voor de minWorkerThreads parameter is 1. U wordt aangeraden de waarde voor de minWorkerThreads parameter in te stellen op de volgende waarde:

minWorkerThreads = maxWorkerThreads / 2

Standaard is de minWorkerThreads parameter niet aanwezig in het Web.config-bestand of het Machine.config-bestand . Deze instelling wordt impliciet vermenigvuldigd met het aantal CPU's.

Maxconnection

De maxconnection parameter bepaalt hoeveel verbindingen met een specifiek IP-adres kunnen worden gemaakt. De parameter wordt als volgt weergegeven:

<connectionManagement>
    <add address="*" maxconnection="2">
    <add address="http://65.53.32.230" maxconnection="12">
</connectionManagement>

Als de code van de toepassing verwijst naar de toepassing op hostnaam in plaats van ip-adres, moet de parameter er als volgt uitzien:

<connectionManagement>
    <add address="*" maxconnection="2">
    <add address="http://hostname" maxconnection="12">
</connectionManagement>

Als de toepassing ten slotte wordt gehost op een andere poort dan 80, moet de parameter de niet-standaardpoort in de URL opnemen, vergelijkbaar met de onderstaande:

<connectionManagement>
    <add address="*" maxconnection="2">
    <add address="http://hostname:8080" maxconnection="12">
</connectionManagement>

De instellingen voor de parameters die eerder in dit artikel zijn besproken, bevinden zich allemaal op procesniveau. maxconnection De parameterinstelling is echter van toepassing op het niveau AppDomain. Omdat deze instelling van toepassing is op het niveau AppDomain, kunt u standaard maximaal twee verbindingen maken met een specifiek IP-adres van elk AppDomain in uw proces.

ExecutionTimeout

ASP.NET gebruikt de volgende configuratie-instelling om de uitvoeringstijd van de aanvraag te beperken:

<httpRuntime executionTimeout="90"/>

U kunt deze limiet ook instellen met behulp van de Server.ScriptTimeout eigenschap.

Opmerking

Als u de waarde van de executionTimeout parameter verhoogt, moet u mogelijk ook de processModelresponseDeadlockInterval parameterinstelling wijzigen.

Aanbevelingen

De instellingen die in deze sectie worden aanbevolen, werken mogelijk niet voor alle toepassingen. De volgende aanvullende informatie kan u echter helpen om de juiste aanpassingen aan te brengen.

Als u één webservice-aanroep doet naar één IP-adres vanaf elke ASPX-pagina, raadt Microsoft u aan de volgende configuratie-instellingen te gebruiken:

  • Stel de waarden van de maxWorkerThreads parameter en de maxIoThreads parameter in op 100.
  • Stel de waarde van de maxconnection parameter in op 12*N (waarbij N het aantal CPU's is dat u hebt).
  • Stel de waarden van de minFreeThreads parameter in op 88*N en de minLocalRequestFreeThreads parameter op 76*N.
  • Stel de waarde van minWorkerThreadsin op 50. minWorkerThreads Onthoud dat het zich niet standaard in het configuratiebestand bevindt. U moet deze toevoegen.

Sommige van deze aanbevelingen hebben betrekking op een eenvoudige formule die het aantal CPU's op een server omvat. De variabele die het aantal CPU's in de formules aangeeft, is N.

Als u hyperthreading hebt ingeschakeld voor deze instellingen, moet u het aantal logische CPU's gebruiken in plaats van het aantal fysieke CPU's. Als u bijvoorbeeld een server met vier processors hebt waarvoor hyperthreading is ingeschakeld, is de waarde van N in de formules 8 in plaats van 4.

Opmerking

Wanneer u deze configuratie gebruikt, kunt u maximaal 12 ASP.NET aanvragen per CPU tegelijk uitvoeren, omdat 100-88=12. Daarom zijn ten minste 88*N worker-threads en 88*N-threads voor voltooiingspoorten beschikbaar voor andere doeleinden (zoals voor de callbacks van de webservice).

U hebt bijvoorbeeld een server met vier processors en hyperthreading ingeschakeld. Op basis van deze formules gebruikt u de volgende waarden voor de configuratie-instellingen die in dit artikel worden vermeld.

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

Wanneer u deze configuratie gebruikt, zijn er 12 verbindingen per CPU per IP-adres beschikbaar voor elk AppDomain. Daarom treedt in het volgende scenario heel weinig conflicten op wanneer aanvragen wachten op verbindingen en de ThreadPool niet is uitgeput:

  • Het web host slechts één toepassing (AppDomain).
  • Bij elke aanvraag voor een ASPX-pagina wordt één webserviceaanvraag ingediend.
  • Alle aanvragen zijn naar hetzelfde IP-adres.

Wanneer u deze configuratie gebruikt, gebruiken scenario's met een van de onderstaande configuratie waarschijnlijk te veel verbindingen:

  • Aanvragen zijn naar meerdere IP-adressen.
  • Aanvragen worden omgeleid (302-statuscode).
  • Voor aanvragen is verificatie vereist.
  • Aanvragen worden gedaan vanuit meerdere AppDomains.

In deze scenario's is het een goed idee om een lagere waarde te gebruiken voor de maxconnection parameter en hogere waarden voor de minFreeThreads parameter en de minLocalRequestFreeThreads parameter.

Meer informatie

Zie Prestaties van ASP.NET verbeteren voor meer informatie.

Als u slechte prestaties en conflicten ondervindt op IIS in combinatie met ASP.NET, gaat u naar de volgende Microsoft-blogs: