Leistungsprobleme beim Aufrufen von Webdiensten aus einer ASP.NET-Anwendung
Dieser Artikel enthält Hilfe zum Beheben von Leistungsproblemen, die auftreten, wenn Sie Webdienste von einer Microsoft ASP.NET-Anwendung aufrufen.
Ursprüngliche Produktversion: ASP.NET
Ursprüngliche KB-Nummer: 821268
Problembeschreibung
Wenn Sie Webdienste von einer ASP.NET-Anwendung aufrufen, können Konflikte, schlechte Leistung und Deadlocks auftreten. Clients können melden, dass Anforderungen nicht mehr antworten oder lange dauern, bis sie ausgeführt werden. Wenn ein Deadlock vermuten wird, wird der Arbeitsprozess möglicherweise wiederverwendet.
Beim Aufrufen der Methode wird möglicherweise die folgende Ausnahmefehlermeldung HttpWebRequest.GetResponse angezeigt:
"System.InvalidOperationException: Es waren nicht genügend freie Threads im ThreadPool-Objekt vorhanden, um den Vorgang abzuschließen."
Möglicherweise wird auch die folgende Ausnahmefehlermeldung im Browser angezeigt:
"HttpException (0x80004005): Anforderungstimeout."
Hinweis
Dieser Artikel gilt auch für Anwendungen, die HttpWebRequest Anforderungen direkt stellen.
Ursache
Dieses Problem kann auftreten, da ASP.NET die Anzahl der Arbeitsthreads und Abschlussportthreads einschränkt, die ein Aufruf zum Ausführen von Anforderungen verwenden kann.
In der Regel verwendet ein Aufruf eines Webdiensts einen Arbeitsthread, um den Code auszuführen, der die Anforderung sendet, und einen Abschlussportthread, um den Rückruf vom Webdienst zu empfangen. Wenn die Anforderung jedoch umgeleitet wird oder eine Authentifizierung erforderlich ist, kann der Aufruf bis zu zwei Arbeitsthreads und zwei Abschlussportthreads verwenden. Sie können also die verwaltete Funktionalität aufgebraucht haben, ThreadPool wenn mehrere Webdienstaufrufe gleichzeitig ausgeführt werden.
Nehmen wir beispielsweise an, dass der Wert ThreadPool auf 10 Arbeitsthreads beschränkt ist und dass derzeit alle 10 Arbeitsthreads Code ausführen, der auf die Ausführung eines Rückrufs wartet. Der Rückruf kann nie ausgeführt werden, da alle Arbeitsaufgaben, die in die Warteschlange eingereiht ThreadPool sind, blockiert werden, bis ein Thread verfügbar ist.
Eine weitere potenzielle Quelle des Konfliktes ist der maxconnection Parameter, den der System.Net Namespace verwendet, um die Anzahl der Verbindungen zu begrenzen. Im Allgemeinen funktioniert dieser Grenzwert wie erwartet. Wenn viele Anwendungen jedoch gleichzeitig versuchen, viele Anforderungen an eine einzelne IP-Adresse zu stellen, müssen Threads möglicherweise auf eine verfügbare Verbindung warten.
Lösung
Um diese Probleme zu beheben, können Sie die folgenden Parameter in der Machine.config Datei an Ihre Situation anpassen:
maxWorkerThreadsminWorkerThreadsmaxIoThreadsminFreeThreadsminLocalRequestFreeThreadsmaxconnectionexecutionTimeout
Um diese Probleme erfolgreich zu beheben, führen Sie die folgenden Aktionen aus:
- Beschränken Sie die Anzahl der ASP.NET Anforderungen, die gleichzeitig ausgeführt werden können, auf ca. 12 pro CPU.
- Zulassen, dass Webdienstrückrufe Threads in der
ThreadPool. - Wählen Sie einen geeigneten Wert für den
maxconnectionsParameter aus. Basieren Sie bei Ihrer Auswahl auf der Anzahl der verwendeten IP-Adressen und AppDomains.
Hinweis
Die Empfehlung, die Anzahl der ASP.NET Anforderungen auf 12 pro CPU zu beschränken, ist etwas willkürlich. Dieser Grenzwert hat sich jedoch für die meisten Anwendungen als gut erwiesen.
MaxWorkerThreads und maxIoThreads
ASP.NET verwendet die folgenden beiden Konfigurationseinstellungen, um die maximale Anzahl von Arbeitsthreads und Abschlussthreads einzuschränken, die verwendet werden:
<processModel maxWorkerThreads="20" maxIoThreads="20">
Der maxWorkerThreads Parameter und der Parameter werden implizit mit der Anzahl der maxIoThreads CPUs multipliziert. Wenn Sie beispielsweise über zwei Prozessoren verfügen, beträgt die maximale Anzahl von Arbeitsthreads 2 * maxWorkerThreads .
MinFreeThreads und minLocalRequestFreeThreads
ASP.NET enthält außerdem die folgenden Konfigurationseinstellungen, die bestimmen, wie viele Arbeitsthreads und Abschlussportthreads zum Starten einer Remoteanforderung oder einer lokalen Anforderung verfügbar sein müssen:
<httpRuntime minFreeThreads="8" minLocalRequestFreeThreads="8">
Wenn nicht genügend Threads verfügbar sind, wird die Anforderung in die Warteschlange eingereiht, bis genügend Threads für die Anforderung verfügbar sind. Daher führen ASP.NET nicht mehr als die folgende Anzahl von Anforderungen gleichzeitig aus:
( maxWorkerThreads * Anzahl der CPUs) - minFreeThreads
Hinweis
Der minFreeThreads Parameter und der Parameter werden nicht implizit mit der Anzahl der minLocalRequestFreeThreads CPUs multipliziert.
MinWorkerThreads
ASP.NET enthält außerdem die folgende Konfigurationseinstellung, die bestimmt, wie viele Arbeitsthreads sofort für die Durchführung einer Remoteanforderung verfügbar gemacht werden können.
<processModel minWorkerThreads="1">
Threads, die von dieser Einstellung gesteuert werden, können wesentlich schneller erstellt werden als Arbeitsthreads, die anhand der Standardthreadoptimierungsfunktionen der Common Language Runtime (CLR) erstellt werden.
Diese Einstellung ermöglicht ASP.NET Serviceanforderungen, die aufgrund einer Verlangsamung auf einem Back-End-Server, eines plötzlichen Schubs von Anforderungen vom Clientende oder eines ähnlichen Vorgangs, der zu einem plötzlichen Anstieg der Anforderungen in der Warteschlange führen würde, plötzlich die ASP.NET Anforderungswarteschlange füllen können.
Der Standardwert für den minWorkerThreads Parameter ist 1. Es wird empfohlen, den Wert für den minWorkerThreads Parameter auf den folgenden Wert festzulegen:
minWorkerThreads = maxWorkerThreads / 2
Standardmäßig ist der minWorkerThreads Parameter weder in der Web.config- noch in der Machine.config-Datei vorhanden. Diese Einstellung wird implizit mit der Anzahl der CPUs multipliziert.
Maxconnection
Der maxconnection Parameter bestimmt, wie viele Verbindungen mit einer bestimmten IP-Adresse hergestellt werden können. Der Parameter wird wie folgt angezeigt:
<connectionManagement>
<add address="*" maxconnection="2">
<add address="http://65.53.32.230" maxconnection="12">
</connectionManagement>
Wenn der Code der Anwendung auf die Anwendung anhand des Hostnamens anstelle der IP-Adresse verweist, sollte der Parameter wie folgt angezeigt werden:
<connectionManagement>
<add address="*" maxconnection="2">
<add address="http://hostname" maxconnection="12">
</connectionManagement>
Wenn die Anwendung auf einem anderen Port als 80 gehostet wird, muss der Parameter den nicht standardmäßigen Port in die URL einschließen, ähnlich wie unten:
<connectionManagement>
<add address="*" maxconnection="2">
<add address="http://hostname:8080" maxconnection="12">
</connectionManagement>
Die Einstellungen für die Parameter, die weiter oben in diesem Artikel behandelt werden, sind alle auf Prozessebene. Die Parametereinstellung gilt jedoch maxconnection für die AppDomain-Ebene. Da diese Einstellung standardmäßig auf die AppDomain-Ebene angewendet wird, können Sie maximal zwei Verbindungen mit einer bestimmten IP-Adresse von jeder AppDomain in Ihrem Prozess erstellen.
ExecutionTimeout
ASP.NET verwendet die folgende Konfigurationseinstellung, um die Ausführungszeit der Anforderung zu begrenzen:
<httpRuntime executionTimeout="90"/>
Sie können diesen Grenzwert auch mithilfe der Server.ScriptTimeout Eigenschaft festlegen.
Hinweis
Wenn Sie den Wert des executionTimeout Parameters erhöhen, müssen Sie möglicherweise auch die processModel responseDeadlockInterval Parametereinstellung ändern.
Empfehlungen
Die in diesem Abschnitt empfohlenen Einstellungen funktionieren möglicherweise nicht für alle Anwendungen. Die folgenden zusätzlichen Informationen können Ihnen jedoch dabei helfen, die entsprechenden Anpassungen vorzunehmen.
Wenn Sie von jeder ASPX-Seite einen Webdienstaufruf an eine einzelne IP-Adresse ausführen, empfiehlt Microsoft die Verwendung der folgenden Konfigurationseinstellungen:
- Legen Sie die Werte des
maxWorkerThreadsParameters und des Parameters aufmaxIoThreads100 fest. - Legen Sie den Wert des
maxconnectionParameters auf 12 * N fest (wobei N die Anzahl der cpUs ist, die Sie haben). - Legen Sie die Werte des
minFreeThreadsParameters auf 88 * N und denminLocalRequestFreeThreadsParameter auf 76 * N fest. - Legen Sie den Wert
minWorkerThreadsauf 50 fest. Denken Sie daran,minWorkerThreadsdass sie nicht standardmäßig in der Konfigurationsdatei enthalten ist. Sie müssen es hinzufügen.
Einige dieser Empfehlungen umfassen eine einfache Formel, die die Anzahl der CPUs auf einem Server umfasst. Die Variable, die die Anzahl der CPUs in den Formeln darstellt, ist N.
Wenn Sie für diese Einstellungen Hyperthreading aktiviert haben, müssen Sie die Anzahl der logischen CPUs anstelle der Anzahl der physischen CPUs verwenden. Wenn Sie beispielsweise einen Server mit vier Prozessoren haben, auf dem Hyperthreading aktiviert ist, lautet der Wert von N in den Formeln 8 anstelle von 4.
Hinweis
Wenn Sie diese Konfiguration verwenden, können Sie maximal 12 ASP.NET Anforderungen pro CPU gleichzeitig ausführen, da 100-88= 12 beträgt. Daher sind mindestens 88 N-Workerthreads * und 88 N-Abschlussportthreads * für andere Verwendungen verfügbar (z. B. für Webdienstrückrufe).
Beispielsweise ist ein Server mit vier Prozessoren und Hyperthreading aktiviert. Basierend auf diesen Formeln würden Sie die folgenden Werte für die konfigurationseinstellungen verwenden, die in diesem Artikel erwähnt werden.
<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>
Wenn Sie diese Konfiguration verwenden, sind außerdem 12 Verbindungen pro CPU pro IP-Adresse für jede AppDomain verfügbar. Daher tritt im folgenden Szenario nur sehr wenig Konflikte auf, wenn Anforderungen auf Verbindungen warten und der ThreadPool nicht aufgebraucht ist:
- Das Web hostet nur eine Anwendung (AppDomain).
- Jede Anforderung für eine ASPX-Seite stellt eine Webdienstanforderung.
- Alle Anforderungen gelten für dieselbe IP-Adresse.
Wenn Sie diese Konfiguration verwenden, verwenden Szenarien, die eine der folgenden Szenarien betreffen, wahrscheinlich zu viele Verbindungen:
- Anforderungen gelten für mehrere IP-Adressen.
- Anforderungen werden umgeleitet (302-Statuscode).
- Anforderungen erfordern eine Authentifizierung.
- Anforderungen werden von mehreren AppDomains gestellt.
In diesen Szenarien empfiehlt es sich, einen niedrigeren Wert für den Parameter und höhere Werte für den Parameter und den Parameter zu maxconnection minFreeThreads minLocalRequestFreeThreads verwenden.
Weitere Informationen
Weitere Informationen finden Sie unter Verbessern ASP.NET Leistung.
Wenn Sie eine schlechte Leistung und Konflikte mit IIS zusammen mit ASP.NET haben, wechseln Sie zu den folgenden Microsoft-Blogs: