Leistungsprobleme beim Aufrufen von Webdiensten aus einer ASP.NET-Anwendung

Dieser Artikel bietet Hilfe zum Beheben von Leistungsproblemen, die auftreten, wenn Sie Webdienste von einer Microsoft ASP.NET-Anwendung aufrufen.

              Originale Produktversion: ASP.NET
Ursprüngliche KB-Nummer: 821268

Symptome

Wenn Sie Webdienste von einer ASP.NET-Anwendung aufrufen, können Konflikte, schlechte Leistung und Deadlocks auftreten. Clients können berichten, dass Anforderungen nicht mehr reagieren oder die Ausführung sehr lange dauert. Wenn ein Deadlock vermutet wird, kann der Arbeitsprozess wiederverwendet werden.

Möglicherweise erhalten Sie die folgende Ausnahmefehlermeldung, wenn Sie die -Methode aufrufen HttpWebRequest.GetResponse :

"System.InvalidOperationException: Es waren nicht genügend freie Threads im ThreadPool-Objekt vorhanden, um den Vorgang abzuschließen."

Möglicherweise erhalten Sie auch die folgende Ausnahmefehlermeldung im Browser:

"HttpException (0x80004005): Timeout für Anforderung."

Hinweis

Dieser Artikel gilt auch für Anwendungen, die Anforderungen direkt stellen HttpWebRequest .

Ursache

Dieses Problem kann auftreten, weil ASP.NET die Anzahl von 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 erfordert, kann der Aufruf bis zu zwei Arbeitsthreads und zwei Abschlussportthreads verwenden. Sie können also das verwaltete ThreadPool Aufschöpfen, wenn mehrere Webdienstaufrufe gleichzeitig auftreten.

Angenommen, der ThreadPool ist auf 10 Arbeitsthreads beschränkt und alle 10 Arbeitsthreads führen derzeit Code aus, der auf die Ausführung eines Rückrufs wartet. Der Rückruf kann niemals ausgeführt werden, da alle Arbeitselemente, die sich in der ThreadPool Warteschlange befinden, blockiert werden, bis ein Thread verfügbar ist.

Eine weitere potenzielle Konfliktquelle 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 versuchen, viele Anforderungen gleichzeitig an eine einzelne IP-Adresse zu senden, 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 dateiMachine.config optimieren, um Ihre Situation optimal anzupassen:

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

Führen Sie die folgenden Aktionen aus, um diese Probleme erfolgreich zu beheben:

  • Begrenzen Sie die Anzahl der ASP.NET Anforderungen, die gleichzeitig ausgeführt werden können, auf ca. 12 pro CPU.
  • Ermöglichen Sie Webdienstrückrufen die freie Verwendung von ThreadPoolThreads im .
  • Wählen Sie einen geeigneten Wert für den maxconnections Parameter aus. Ihre Auswahl basiert auf der Anzahl der verwendeten IP-Adressen und AppDomains.

Hinweis

Die Empfehlung, die Anzahl der ASP.NET Anforderungen auf 12 pro CPU zu begrenzen, ist etwas willkürlich. Diese Grenze 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 zu begrenzen, die verwendet werden:

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

Der maxWorkerThreads Parameter und der maxIoThreads Parameter werden implizit mit der Anzahl der 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 auch die folgenden Konfigurationseinstellungen, die bestimmen, wie viele Arbeitsthreads und Abschlussportthreads verfügbar sein müssen, um eine Remoteanforderung oder eine lokale Anforderung zu starten:

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

Wenn nicht genügend Threads verfügbar sind, wird die Anforderung in die Warteschlange eingereiht, bis genügend Threads die Anforderung ausführen können. 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 minLocalRequestFreeThreads Parameter werden nicht implizit mit der Anzahl der CPUs multipliziert.

MinWorkerThreads

ASP.NET enthält auch die folgende Konfigurationseinstellung, die bestimmt, wie viele Arbeitsthreads sofort verfügbar gemacht werden können, um eine Remoteanforderung zu verarbeiten.

<processModel minWorkerThreads="1">

Threads, die von dieser Einstellung gesteuert werden, können mit einer viel schnelleren Rate erstellt werden als Arbeitsthreads, die mit den Standardthreadoptimierungsfunktionen der Common Language Runtime (CLR) erstellt werden.

Diese Einstellung ermöglicht ASP.NET, Anforderungen zu verarbeiten, die die ASP.NET Anforderungswarteschlange aufgrund einer Verlangsamung auf einem Back-End-Server, einem plötzlichen Burst von Anforderungen vom Clientende oder ähnlichem plötzlich füllen, was zu einem plötzlichen Anstieg der Anzahl von Anforderungen in der Warteschlange führen würde.

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-Datei 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 sieht wie folgt aus:

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

Wenn der Code der Anwendung anhand des Hostnamens anstelle der IP-Adresse auf die Anwendung verweist, sollte der Parameter wie folgt aussehen:

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

Wenn die Anwendung an einem anderen Port als 80 gehostet wird, muss der Parameter den nicht standardmäßigen Port in der URL enthalten, ähnlich wie im folgenden Beispiel:

<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 erläutert werden, befinden sich alle auf Prozessebene. Die maxconnection Parametereinstellung gilt jedoch für die Ebene AppDomain. Da diese Einstellung für die AppDomain-Ebene gilt, können Sie standardmäßig maximal zwei Verbindungen mit einer bestimmten IP-Adresse aus 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 processModelresponseDeadlockInterval 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 helfen, die entsprechenden Anpassungen vorzunehmen.

Wenn Sie einen Webdienstaufruf an eine einzelne IP-Adresse von jeder ASPX-Seite ausführen, empfiehlt Microsoft, die folgenden Konfigurationseinstellungen zu verwenden:

  • Legen Sie die Werte des maxWorkerThreads Parameters und des maxIoThreads Parameters auf 100 fest.
  • Legen Sie den Wert des maxconnection Parameters auf 12*N fest (wobei N die Anzahl der CPUs ist, die Sie haben).
  • Legen Sie die Werte des minFreeThreads Parameters auf 88*N und den minLocalRequestFreeThreads Parameter auf 76*N fest.
  • Legen Sie den Wert von minWorkerThreads auf 50 fest. Denken Sie daran, minWorkerThreads dass standardmäßig nicht in der Konfigurationsdatei enthalten ist. Sie müssen sie 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 Hyperthreading für diese Einstellungen aktiviert ist, müssen Sie die Anzahl der logischen CPUs anstelle der Anzahl der physischen CPUs verwenden. Wenn Sie beispielsweise einen Server mit vier Prozessoren mit aktiviertem Hyperthreading haben, ist der Wert von N in den Formeln 8 statt 4.

Hinweis

Wenn Sie diese Konfiguration verwenden, können Sie maximal 12 ASP.NET Anforderungen pro CPU gleichzeitig ausführen, da 100-88=12. Daher sind mindestens 88 *N Arbeitsthreads und 88* N-Abschlussportthreads für andere Zwecke (z. B. für Webdienstrückrufe) verfügbar.

Beispielsweise verfügen Sie über einen Server mit vier Prozessoren und aktiviertem Hyperthreading. Basierend auf diesen Formeln würden Sie die folgenden Werte für die in diesem Artikel erwähnten Konfigurationseinstellungen verwenden.

<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 und IP-Adresse für jede AppDomain verfügbar. Daher tritt im folgenden Szenario nur sehr wenig Konflikt auf, wenn Anforderungen auf Verbindungen warten und nicht ThreadPool erschöpft ist:

  • Das Web hostet nur eine Anwendung (AppDomain).
  • Jede Anforderung für eine ASPX-Seite stellt eine Webdienstanforderung.
  • Alle Anforderungen werden an dieselbe IP-Adresse gesendet.

Wenn Sie diese Konfiguration verwenden, verwenden Szenarien mit einer der folgenden Optionen wahrscheinlich zu viele Verbindungen:

  • Anforderungen richten sich an mehrere IP-Adressen.
  • Anforderungen werden umgeleitet (302 status Code).
  • Anforderungen erfordern eine Authentifizierung.
  • Anforderungen werden von mehreren AppDomains gesendet.

In diesen Szenarien empfiehlt es sich, einen niedrigeren Wert für den maxconnection Parameter und höhere Werte für den minFreeThreads Parameter und den minLocalRequestFreeThreads Parameter zu verwenden.

Weitere Informationen

Weitere Informationen finden Sie unter Verbessern der leistung von ASP.NET.

Wenn sie in IIS zusammen mit ASP.NET eine schlechte Leistung und Konflikte feststellen, wechseln Sie zu den folgenden Microsoft-Blogs: