Ein paar tausend Anfragen pro Minute sind eine große Menge Last, und die einzige Möglichkeit, es richtig zu machen, besteht darin, die maximale Anzahl von Threads zu kontrollieren und zu begrenzen, die gleichzeitig ausgeführt werden können.
Da nicht viele Informationen darüber veröffentlicht werden, wie Sie dies implementiert haben. Ich werde einige mögliche Umstände behandeln.
Zeit zum Experimentieren...
Die Konstanten:
- Zu verarbeitende Elemente:
- 50 pro Sekunde , oder anders gesagt...
- 3.000 pro Minute , und eine weitere Sichtweise...
- 180.000 pro Stunde
Die Variablen:
-
Datenübertragungsraten:
-
Wie viele Daten Sie pro Sekunde übertragen können, spielt eine Rolle, egal was wir tun, und dies wird im Laufe des Tages je nach Tageszeit variieren.
Das Einzige, was wir tun können, ist, mehr Anfragen von verschiedenen CPUs abzufeuern, um das Gewicht des Datenverkehrs zu verteilen, den wir hin und her senden.
-
-
Rechenleistung:
-
Ich nehme an, Sie haben dies in einem
WebJob
im Gegensatz dazu, dass dies innerhalb der MVC-Site selbst codiert ist. Es ist sehr ineffizient und nicht für den Zweck geeignet, den Sie erreichen möchten. Durch die Verwendung eines WebJobs können wir uns in die Warteschlange stellen Arbeitselemente, die von anderenWebJobs
verarbeitet werden sollen . Die Warteschlange fraglich ist die Azure Queue Speicherung .
-
Die Probleme:
- Wir versuchen, 50 Transaktionen pro Sekunde abzuschließen, also sollte jede Transaktion in weniger als 1 Sekunde durchgeführt werden, wenn wir 50 Threads verwenden würden. Unsere 45-sekündige Auszeit hat an dieser Stelle keinen Zweck.
- Wir erwarten, dass 50 Threads gleichzeitig laufen und alle in weniger als einer Sekunde jede Sekunde auf einer einzigen CPU abgeschlossen werden. (Ich übertreibe hier, nur um einen Punkt zu machen ... aber stellen Sie sich vor, Sie laden jede Sekunde 50 Textdateien herunter. Verarbeiten und dann versuchen, sie an einen Kollegen zurückzuschicken, in der Hoffnung, dass sie dazu bereit sind fangen)
- Wir brauchen eine Wiederholungslogik, wenn das Element nach 3 Versuchen nicht verarbeitet wird, muss es wieder in die Warteschlange gestellt werden. Idealerweise sollten wir dem Server mehr Zeit geben, um bei jedem Fehler zu reagieren, als nur eine Sekunde, sagen wir, wir haben ihm beim ersten Fehler eine Pause von 2 Sekunden gegeben, dann 4 Sekunden, dann 10, dies erhöht die Wahrscheinlichkeit, dass wir bestehen bleiben / Abrufen der von uns benötigten Daten.
- Wir vermuten dass unsere MongoDb kann diese Anzahl von Anfragen pro Sekunde verarbeiten. Wenn Sie es noch nicht getan haben, suchen Sie nach Möglichkeiten, es zu skalieren. Das Problem liegt nicht in der Tatsache, dass es sich um eine MongoDb handelt, die Datenschicht hätte alles sein können, sondern die Tatsache, dass wir diese Anzahl von Anfragen stellen eine einzelne Quelle, die die wahrscheinlichste Ursache für Ihre Probleme sein wird.
Die Lösung:
- Richten Sie einen
WebJob
ein und nennen Sie ihnEnqueueJob
. DieserWebJob
wird nur einen einzigen Zweck haben, um zu verarbeitende Arbeitselemente in denQueue Storage
einzureihen . - Erstellen Sie einen
Queue Storage Container
namensWorkItemQueue
, dient diese Warteschlange als Auslöser für den nächsten Schritt und startet unsere Skalierungsvorgänge. - Erstellen Sie einen weiteren
WebJob
namensDequeueJob
. DieserWebJob
wird auch einen einzigen Zweck haben, um die Arbeitselemente aus derWorkItemQueue
zu entfernen und senden Sie die Anfragen an Ihren Datenspeicher. - Konfigurieren Sie den
DequeueJob
zu drehen, sobald ein Element in dieWorkItemQueue
platziert wurde , starten Sie 5 separate Threads auf jedem und während die Warteschlange nicht leer ist, entfernen Sie Arbeitselemente für jeden Thread und versuchen Sie, den aus der Warteschlange entfernten Job auszuführen.- Versuch 1, falls fehlschlagen, warten und erneut versuchen.
- Versuch 2, falls fehlschlagen, warten und erneut versuchen.
- Versuch 3, falls fehlschlagen, Element zurück in
WorkItemQueue
einreihen
- Konfigurieren Sie Ihre Website so, dass sie automatisch auf x CPUs skaliert wird (beachten Sie, dass Ihre Website und Webjobs dieselben Ressourcen nutzen)
Hier ist ein kurzes 10-minütiges Video das gibt einen Überblick über die Verwendung von Queue-Speichern und Web-Jobs.
Bearbeiten:
Ein weiterer Grund, warum Sie diese Fehler erhalten, könnte auch auf zwei andere Faktoren zurückzuführen sein, die wiederum dadurch verursacht werden, dass sie sich in einer MVC-App befinden ...
Wenn Sie die Anwendung mit dem DEBUG
kompilieren Attribut angewendet, aber RELEASE
drücken Version, könnten Sie aufgrund der Einstellungen in Ihrer web.config
auf Probleme stoßen , ohne DEBUG
-Attribut führt eine ASP.NET-Webanwendung eine Anfrage maximal 90 Sekunden lang aus. Wenn die Anfrage länger dauert, wird die Anfrage verworfen.
Zum Erhöhen des Zeitlimits auf mehr als 90 Sekunden Sie müssen den [httpRuntime][3]
ändern -Eigenschaft in Ihrer web.config
...
<!-- Increase timeout to five minutes -->
<httpRuntime executionTimeout="300" />
Die andere Sache, die Sie beachten müssen, sind die Timeout-Einstellungen Ihres Browsers> Web-App. Ich würde sagen, wenn Sie darauf bestehen, den Code in MVC zu behalten, anstatt ihn zu extrahieren und in einen WebJob einzufügen, dann Sie können den folgenden Code verwenden, um eine Anfrage an Ihre Web-App zu senden und das Zeitlimit der Anfrage auszugleichen.
string html = string.Empty;
string uri = "http://google.com";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Timeout = TimeSpan.FromMinutes(5);
using (HttpWebResponse response = (HttpWebResonse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
html = reader.ReadToEnd();
}