Wir haben eine API, die mit ServiceStack implementiert wird, das in IIS gehostet wird. Während des Auslastungstests der API haben wir festgestellt, dass die Antwortzeiten gut sind, sich jedoch schnell verschlechtern, sobald wir ungefähr 3.500 gleichzeitige Benutzer pro Server erreichen. Wir haben zwei Server und bei 7.000 Benutzern liegen die durchschnittlichen Antwortzeiten für alle Endpunkte unter 500 ms. Die Boxen befinden sich hinter einem Load Balancer, sodass wir 3.500 Concurrents pro Server erhalten. Sobald wir jedoch die Anzahl der gleichzeitigen Benutzer erhöhen, stellen wir eine signifikante Zunahme der Antwortzeiten fest. Wenn Sie die Anzahl der gleichzeitigen Benutzer auf 5.000 pro Server erhöhen, beträgt die durchschnittliche Antwortzeit pro Endpunkt ca. 7 Sekunden.
Der Arbeitsspeicher und die CPU auf den Servern sind recht niedrig, sowohl bei guten Antwortzeiten als auch nach einer Verschlechterung. In der Spitze mit 10.000 gleichzeitigen Benutzern liegt der CPU-Durchschnitt bei knapp 50% und der RAM-Speicher bei 3-4 GB von 16. Dies lässt uns denken, dass wir irgendwo an eine Grenze stoßen. Der folgende Screenshot zeigt einige Schlüsselindikatoren in perfmon während eines Auslastungstests mit insgesamt 10.000 gleichzeitigen Benutzern. Der hervorgehobene Zähler ist Anfragen / Sekunde. Auf der rechten Seite des Screenshots können Sie sehen, wie die Grafik für Anforderungen pro Sekunde sehr unregelmäßig wird. Dies ist der Hauptindikator für langsame Reaktionszeiten. Sobald wir dieses Muster sehen, stellen wir im Belastungstest langsame Reaktionszeiten fest.
Wie gehen wir vor, um dieses Leistungsproblem zu beheben? Wir versuchen herauszufinden, ob es sich um ein Codierungs- oder Konfigurationsproblem handelt. Gibt es Einstellungen in web.config oder IIS, die dieses Verhalten erklären könnten? Der Anwendungspool führt .NET v4.0 aus und die IIS-Version ist 7.5. Die einzige Änderung, die wir an den Standardeinstellungen vorgenommen haben, ist die Aktualisierung des Werts für die Warteschlangenlänge des Anwendungspools von 1.000 auf 5.000. Wir haben der Datei Aspnet.config auch die folgenden Konfigurationseinstellungen hinzugefügt:
<system.web>
<applicationPool
maxConcurrentRequestsPerCPU="5000"
maxConcurrentThreadsPerCPU="0"
requestQueueLimit="5000" />
</system.web>
Mehr Details:
Der Zweck der API besteht darin, Daten aus verschiedenen externen Quellen zu kombinieren und als JSON zurückzugeben. Derzeit wird eine InMemory-Cache-Implementierung verwendet, um einzelne externe Aufrufe auf der Datenschicht zwischenzuspeichern. Die erste Anforderung an eine Ressource ruft alle erforderlichen Daten ab und alle nachfolgenden Anforderungen für dieselbe Ressource erhalten Ergebnisse aus dem Cache. Wir haben einen 'Cache Runner', der als Hintergrundprozess implementiert ist und die Informationen im Cache in bestimmten Intervallen aktualisiert. Wir haben den Code gesperrt, der Daten aus den externen Ressourcen abruft. Wir haben auch die Dienste zum asynchronen Abrufen der Daten von externen Quellen implementiert, sodass der Endpunkt nur so langsam sein sollte wie der langsamste externe Aufruf (es sei denn, wir haben Daten im Cache). Dies erfolgt mithilfe der System.Threading.Tasks.Task-Klasse.Könnten wir eine Beschränkung in Bezug auf die Anzahl der Threads treffen, die für den Prozess verfügbar sind?