Was begrenzt die Anzahl gleichzeitiger Verbindungen, die meine ASP.NET-Anwendung zu einem Webdienst herstellen kann?

89

Ich habe eine ASP.NET 4.0-Anwendung, die auf IIS 7.5 auf einem 64-Bit-Windows Server 2008 R2 Enterprise-Computer mit RAM, CPU, Festplatte usw. ausgeführt wird.

Bei jeder Webanforderung stellt die ASP.NET-Anwendung eine Verbindung zu einem Backend-Webdienst (über Raw-Sockets) her, der auf demselben Computer ausgeführt wird.

Problem: Es scheint etwas zu geben, das die Anzahl der gleichzeitigen Verbindungen zum Backend-Webdienst einschränkt. Verdächtigerweise liegt die Anzahl der gleichzeitigen Verbindungen bei 16.

Ich habe diesen Schlüsselartikel von Microsoft gefunden, in dem erläutert wird, wie die Einstellungen von IIS angepasst werden, um ASP.NET-Apps aufzunehmen, die viele Webdienstanforderungen stellen: http://support.microsoft.com/?id=821268#tocHeadRef

Ich folgte den Empfehlungen des Artikels, aber immer noch kein Glück. Die Einstellung, die besonders interessant ist maxconnection, ist die Einstellung, die ich sogar auf 999 gestoßen habe.

Irgendwelche Ideen, was sonst noch Verbindungen drosseln könnte?

Hinweis: Wenn ich IIS aus dem Mix herausschneide und die Clients eine direkte Verbindung zum Backend-Webdienst herstellen, werden so viele Verbindungen wie nötig geöffnet, sodass ich mir sicher bin, dass das Backend nicht der Engpass ist. Es muss etwas in IIS / ASP.NET-Land sein.

Hier ist der relevante Abschnitt, von dem machine.configich sicher bin, dass er von der Anwendung gelesen wird (überprüft mit appcmd.exe):

<system.web>
    <processModel autoConfig="false" maxWorkerThreads="100" maxIoThreads="100" minWorkerThreads="50" />
    <httpRuntime minFreeThreads="176" minLocalRequestFreeThreads="152"/>

    <httpHandlers />

    <membership>
        <providers>
            <add name="AspNetSqlMembershipProvider"
                type="System.Web.Security.SqlMembershipProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
                connectionStringName="LocalSqlServer"
                enablePasswordRetrieval="false"
                enablePasswordReset="true"
                requiresQuestionAndAnswer="true"
                applicationName="/"
                requiresUniqueEmail="false"
                passwordFormat="Hashed"
                maxInvalidPasswordAttempts="5"
                minRequiredPasswordLength="7"
                minRequiredNonalphanumericCharacters="1"
                passwordAttemptWindow="10"
                passwordStrengthRegularExpression="" />
        </providers>
    </membership>

    <profile>
        <providers>
            <add name="AspNetSqlProfileProvider" connectionStringName="LocalSqlServer" applicationName="/"
                type="System.Web.Profile.SqlProfileProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </providers>
    </profile>

    <roleManager>
        <providers>
            <add name="AspNetSqlRoleProvider" connectionStringName="LocalSqlServer" applicationName="/"
                type="System.Web.Security.SqlRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add name="AspNetWindowsTokenRoleProvider" applicationName="/"
                type="System.Web.Security.WindowsTokenRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </providers>
    </roleManager>
</system.web>
<system.net>
    <connectionManagement>
        <add address="*" maxconnection="999"/>
    </connectionManagement>
</system.net>
Rob Sobers
quelle
@DanB hat hier einen guten Punkt - wie messen Sie die Anzahl der gleichzeitigen Verbindungen?
Jeremy McGee
@JeremyMcGee Ich messe die Anzahl der gleichzeitigen Verbindungen, indem ich TCPView auf dem Server ausführe, um festzustellen, wie viele Backend-Verbindungen von den IIS-Worker-Prozessen hergestellt werden.
Rob Sobers
Laufen die Webclients auf unabhängigen Computern oder auf demselben Computer? (Überprüfen, ob keine clientseitige Drosselung stattfindet.)
Jeremy McGee
3
@JeremyMcGee Separate Maschinen. 1 Client-Server-Verbindung pro Computer. Wir wissen auch, dass es irgendwo im Netzwerk keine Drosselung gibt, denn wenn wir direkt auf das Backend zugreifen (was auch über HTTP geschieht), stoßen wir nicht auf einen Engpass.
Rob Sobers
1
Rob, hast du jemals eine endgültige Lösung dafür gefunden?
ElectronicKT

Antworten:

103

Die meisten der hier bereitgestellten Antworten beziehen sich auf die Anzahl der eingehenden Anforderungen an Ihren Backend-Webservice und nicht auf die Anzahl der ausgehenden Anforderungen, die Sie von Ihrer ASP.net-Anwendung an Ihren Backend-Dienst stellen können.

Es ist nicht Ihr Backend-Webservice, der Ihre Anforderungsrate hier drosselt, sondern die Anzahl der offenen Verbindungen, die Ihre aufrufende Anwendung zum selben Endpunkt (derselben URL) herstellen möchte.

Sie können diese Einschränkung aufheben, indem Sie der Datei machine.config den folgenden Konfigurationsabschnitt hinzufügen:

<configuration>
  <system.net>
    <connectionManagement>
      <add address="*" maxconnection="65535"/>
    </connectionManagement>
  </system.net>
</configuration>

Sie können natürlich eine vernünftigere Anzahl auswählen, wenn Sie 50 oder 100 gleichzeitige Verbindungen wünschen. Aber das oben genannte öffnet es bis zu max. Sie können auch eine bestimmte Adresse für die oben genannte Open-Limit-Regel anstelle des '*' angeben, das alle Adressen angibt.

MSDN-Dokumentation für System.Net.connectionManagement

Eine weitere großartige Ressource zum Verständnis von ConnectManagement in .NET

Hoffe das löst dein Problem!

EDIT: Ups, ich sehe, dass Sie die in Ihrem Code oben erwähnte Verbindungsverwaltung haben. Ich werde meine obigen Informationen belassen, da sie für zukünftige Anfragen mit demselben Problem relevant sind. Bitte beachten Sie jedoch, dass sich derzeit 4 verschiedene machine.config-Dateien auf den aktuellsten Servern befinden!

Es gibt .NET Framework v2, das sowohl unter 32-Bit als auch unter 64-Bit ausgeführt wird, sowie .NET Framework v4, das sowohl unter 32-Bit als auch unter 64-Bit ausgeführt wird. Abhängig von Ihren gewählten Einstellungen für Ihren Anwendungspool können Sie eine dieser 4 verschiedenen machine.config-Dateien verwenden! Bitte überprüfen Sie alle 4 machine.config-Dateien, die sich normalerweise hier befinden:

  • C: \ Windows \ Microsoft.NET \ Framework \ v2.0.50727 \ CONFIG
  • C: \ Windows \ Microsoft.NET \ Framework64 \ v2.0.50727 \ CONFIG
  • C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ Config
  • C: \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319 \ Config
BenSwayne
quelle
Ja, ich habe diese Basis abgedeckt. Trotzdem danke, @BenSwayne! Ich habe überprüft, ob ich das richtige geändert habe machine.config(64-Bit 4.0).
Rob Sobers
@RobSobers: In diesem Fall wäre ich dem Implementierungscode etwas misstrauisch. Vielleicht gehen dir die Fäden aus oder so? Können Sie Ihren TcpClient-Webservice-Aufrufcode in eine Konsolen-App werfen und sehen, ob Sie eine bessere Anforderungsrate erzielen können? Dies zeigt, ob es sich um eine IIS-spezifische Konfiguration oder eine umfassendere .NET-Konfiguration oder Ihren Code handelt.
BenSwayne
Geht diese Zeile in den Client-Computer?
Uri Abramson
Vielen Dank, Ihre Einstellungen werden mit processModel-Twekaing von codeproject.com/Articles/133738/… kombiniert. "ISAPI 'C: \ windows \ Microsoft.Net \ Framework \ v2.0.050727 \ aspnet_isapi.dll' wurde aus folgendem Grund als ungesund gemeldet : 'Deadlock erkannt "Problem
Zakos
@BenSwayne gilt das gleiche Konzept auch für SMTP-Verbindungen? Ich entwerfe eine Anwendung zum Senden von Massen-E- Mails. Ist diese ConnectionManagement- Eigenschaft auch beim Senden von Massen-E-Mails hilfreich (Verwendung von Multithreading für die Funktion mail.send )?
Vibs2006
7

Mir ist klar, dass die Frage vielleicht ziemlich alt ist, aber Sie sagen, dass das Backend auf demselben Server ausgeführt wird. Das heißt, an einem anderen Port, wahrscheinlich anders als am Standardport 80.

Ich habe gelesen, dass Sie bei Verwendung des Konfigurationselements "connectionManagement" die Portnummer angeben müssen, wenn diese von der Standardnummer 80 abweicht.

LINK: Die Einstellung maxConnection funktioniert möglicherweise nicht einmal autoConfig = false in ASP.NET

Zweitens, wenn Sie die Standardkonfiguration (address = "*") verwenden, die um Ihren eigenen Backend-spezifischen Wert erweitert wurde, können Sie den spezifischen Wert an die erste Stelle setzen! Andernfalls stimmt bei einer Anforderung das * zuerst überein und der Standardwert von 2 Verbindungen wird übernommen. Genau wie wenn Sie den Abschnitt in web.config verwenden.

LINK: <Entfernen> -Element für das Verbindungsmanagement (Netzwerkeinstellungen)

Hoffe es hilft jemandem.

Sebastian Hek
quelle
5

Könnte es sein, dass Sie eine WCF-basierte Webdienstreferenz verwenden? Standardmäßig ist ServiceThrottlingBehavior.MaxConcurrentCalls 16.

Sie können versuchen, das <serviceThrottling>Element Ihres Dienstreferenzverhaltens zu aktualisieren

<serviceThrottling
    maxConcurrentCalls="999" 
    maxConcurrentSessions="999" 
    maxConcurrentInstances="999" />

(Beachten Sie, dass ich die obigen Einstellungen empfehlen würde.) Weitere Informationen zum Konfigurieren eines geeigneten Elements finden Sie unter MSDN<behavior> .

Ruben
quelle
Ich wünschte, wir wären es, aber wir sind es nicht. Der verwendete Dienst wird in Apache / Python / mod_wsgi auf einem anderen Computer ausgeführt, und wie Rob erwähnt hat, ist dies eindeutig nicht das Problem.
Benjamin Pollack
Servicereferenzen befinden sich auf dem Client. Wie nutzt Ihr Client den Apache-Dienst?
John Saunders
Wie John sagte: Die Drosselung wird auf dem Client eingestellt, der den Webdienst konsumiert. Vielleicht ist der Ausdruck "Ihr Serviceverhalten" etwas irreführend. Ist es sinnvoller, wenn es als "Ihr Service-Referenzverhalten" formuliert wird?
Ruben
@john Es wird über a konsumiert TcpClient(der Dienst verkauft benutzerdefinierte binäre Blobs, nicht WCF / SOAP oder ähnliches). Diese Konfigurationsoptionen scheinen rein zu beeinflussen Sie , wenn Sie verwenden ServiceHost, nicht TcpClient; vermisse ich etwas
Benjamin Pollack
Warum nicht "Add Service Reference" verwenden?
John Saunders
3

Haben Sie versucht, den Wert der statischen DefaultConnectionLimit- Eigenschaft programmgesteuert festzulegen ?

Hier finden Sie eine gute Informationsquelle zu diesen echten Kopfschmerzen ... ASP.NET-Thread-Verwendung unter IIS 7.5, IIS 7.0 und IIS 6.0 mit Updates für Framework 4.0.

Simon Mourier
quelle
Ich stelle mir vor, das sollte keine Rolle spielen, aber ich werde es trotzdem versuchen.
Rob Sobers
So haben wir es vor ein paar Jahren behoben. Wir hatten Parallelitätsprobleme und dies schien es zu klären. Net.ServicePointManager.DefaultConnectionLimit = 1000 haben wir verwendet. Sie müssen es festlegen, bevor Sie Verbindungsklassen erstellen.
Brain2000
2

Siehe den Abschnitt "Threading" auf dieser Seite: http://msdn.microsoft.com/en-us/library/ff647786.aspx in Verbindung mit dem Abschnitt "Verbindungen".

Haben Sie versucht, das maxconnection-Attribut Ihrer processModel-Einstellung zu erhöhen?

Matt Evans
quelle
Ja, habe ich. Der von Ihnen zitierte Artikel weist jedoch auf etwas Interessantes hin, maxconnectiondas in keinem anderen Artikel zu diesem Thema erwähnt wurde: Das Attribut gilt nicht für lokale Webdienstaufrufe. In diesem speziellen Fall des Web - Service ist vor Ort, aber wir haben das gleiche Problem in einem anderen Umfeld , in dem der Dienst nicht lokal ist.
Rob Sobers
@RobSobers - Ich denke, dass der obige Link einen zweiten Blick wert ist. Überprüfen Sie den Teil über minLocalRequestFreeThreads- Dieser Arbeitsprozess verwendet diese Einstellung, um Anforderungen von localhost (bei denen eine Webanwendung einen Webdienst auf demselben Server aufruft) in die Warteschlange zu stellen, wenn die Anzahl der verfügbaren Threads im Thread-Pool unter diese Anzahl fällt. Diese Einstellung ähnelt minFreeThreads, gilt jedoch nur für Anforderungen, die localhost verwenden .
Ahmad
@ Ahmad Yup, ich habe auch gesetzt minLocalRequestFreeThreads(siehe meine machine.configin der Frage.
Rob Sobers
0

Wenn es nicht in dem Webdienst oder der Anwendung oder dem Server (Apache oder IIS) definiert ist, auf dem bzw. der das Webdienst-Verbrauchsmaterial gehostet wird, können Sie bis zum Ausfall unendlich viele Verbindungen herstellen

Frank Tudor
quelle
0

Während ich Leistungstests durchführe, ist das Maß, nach dem ich gehe, RPS, dh wie viele Anforderungen pro Sekunde kann der Server innerhalb einer akzeptablen Latenz bedienen.

Theoretisch kann ein Server nur so viele Anforderungen gleichzeitig ausführen wie die Anzahl der Kerne.

Es sieht nicht so aus, als ob das Problem das Threading-Modell von ASP.net ist, da es möglicherweise Tausende von RPS bedienen kann. Es scheint, dass das Problem Ihre Anwendung sein könnte. Verwenden Sie Synchronisationsprimitive?

Wie hoch ist auch die Latenz Ihrer Webdienste? Sie reagieren sehr schnell (innerhalb von Mikrosekunden). Wenn nicht, sollten Sie asynchrone Anrufe in Betracht ziehen, damit Sie nicht blockieren

Wenn dies nicht funktioniert, möchten Sie Ihren Code möglicherweise mit Visual Studio oder Redgate Profiler profilieren

np-hart
quelle