Een paar duizend verzoeken per minuut is een grote load, en de enige manier om het goed te doen, is door het maximale aantal threads dat tegelijkertijd kan worden uitgevoerd te controleren en te beperken.
Omdat er niet veel informatie is gepost over hoe je dit hebt geïmplementeerd. Ik ga een paar mogelijke omstandigheden bespreken.
Tijd om te experimenteren...
De constanten:
- Te verwerken items:
- 50 per seconde , of met andere woorden...
- 3.000 per minuut , en nog een manier om ernaar te kijken...
- 180.000 per uur
De variabelen:
-
Gegevensoverdrachtsnelheden:
-
Hoeveel gegevens u per seconde kunt overdragen, zal een rol spelen, wat we ook doen, en dit varieert gedurende de dag, afhankelijk van het tijdstip van de dag.
Het enige wat we kunnen doen is meer verzoeken van verschillende cpu's afvuren om het gewicht van het verkeer dat we heen en weer sturen te verdelen.
-
-
Verwerkingskracht:
-
Ik neem aan dat je dit hebt in een
WebJob
in tegenstelling tot dit gecodeerd te hebben in de MVC-site zelf. Het is zeer inefficiënt en niet geschikt voor het doel dat u probeert te bereiken. Door een WebJob te gebruiken, kunnen we in de wachtrij zetten werkitems die moeten worden verwerkt door andereWebJobs
. De wachtrij in kwestie is de Azure Queue Opslag .
-
De problemen:
- We proberen 50 transacties per seconde te voltooien, dus elke transactie zou in minder dan 1 seconde moeten worden gedaan als we 50 threads zouden gebruiken. Onze time-out van 45 seconden heeft op dit moment geen zin.
- We verwachten dat 50 threads gelijktijdig zullen draaien, en allemaal binnen een seconde, elke seconde, op een enkele cpu. (Ik overdrijf hier een punt, gewoon om een punt te maken ... maar stel je voor dat je elke seconde 50 tekstbestanden downloadt. Verwerk het en probeer het dan terug te sturen naar een collega in de hoop dat ze zelfs klaar zijn om vang het)
- We moeten een logica voor opnieuw proberen hebben, als het item na 3 pogingen niet is verwerkt, moeten ze weer in de wachtrij worden geplaatst. In het ideale geval zouden we de server meer tijd moeten geven om te reageren dan slechts één seconde bij elke storing, laten we zeggen dat we hem een pauze van 2 seconden hebben gegeven bij de eerste storing, dan 4 seconden, dan 10, dit zal de kans dat we volharden aanzienlijk vergroten / het ophalen van de gegevens die we nodig hadden.
- We nemen aan dat dat onze MongoDb kan dit aantal verzoeken per seconde aan. Als je dat nog niet hebt gedaan, ga dan kijken naar manieren om het uit te schalen. Het probleem ligt niet in het feit dat het een MongoDb is, de gegevenslaag kan van alles zijn, het is het feit dat we dit aantal verzoeken doen van één enkele bron die de meest waarschijnlijke oorzaak van uw problemen zal zijn.
De oplossing:
- Een
WebJob
instellen en noem hetEnqueueJob
. DezeWebJob
heeft maar één doel, werkstukken in de wachtrij plaatsen om te worden verwerkt in deQueue Storage
. - Maak een
Queue Storage Container
genaamdWorkItemQueue
, zal deze wachtrij fungeren als een trigger voor de volgende stap en het begin van onze uitschaaloperaties. - Maak nog een
WebJob
genaamdDequeueJob
. DezeWebJob
heeft ook maar één doel, namelijk om de werkitems uit deWorkItemQueue
te halen en vuur de verzoeken naar uw gegevensopslag af. - Configureer de
DequeueJob
om te draaien zodra een item in deWorkItemQueue
is geplaatst , start 5 afzonderlijke threads op elk en terwijl de wachtrij niet leeg is, verwijdert u werkitems voor elke thread en probeert u de uit de wachtrij verwijderde taak uit te voeren.- Poging 1, indien mislukt, wacht en probeer opnieuw.
- Poging 2, indien mislukt, wacht en probeer het opnieuw.
- Poging 3, indien mislukt, item terug in wachtrij plaatsen in
WorkItemQueue
- Configureer uw website om automatisch uit te schalen naar x aantal cpu's (merk op dat uw website en webtaken dezelfde bronnen delen)
Hier is een korte video van 10 minuten die een overzicht geeft van het gebruik van wachtrijopslag en webtaken.
Bewerken:
Een andere reden waarom u deze fouten kunt krijgen, kan ook zijn vanwege twee andere factoren, opnieuw veroorzaakt doordat het zich in een MVC-app bevindt...
Als u de applicatie compileert met de DEBUG
attribuut toegepast maar op RELEASE
. drukken in plaats daarvan kunt u problemen ondervinden vanwege de instellingen in uw web.config
, zonder de DEBUG
attribuut, zal een ASP.NET-webtoepassing een verzoek uitvoeren voor maximaal 90 seconden, als het verzoek langer duurt, wordt het verzoek verwijderd.
De time-out verlengen tot langer dan 90 seconden je moet de [httpRuntime][3]
. wijzigen eigenschap in uw web.config
...
<!-- Increase timeout to five minutes -->
<httpRuntime executionTimeout="300" />
Het andere waar u rekening mee moet houden, zijn de time-outinstellingen voor aanvragen van uw browser> webapp, ik zou zeggen dat als u erop staat de code in MVC te houden in plaats van deze uit te pakken en in een WebJob te plaatsen, u kan de volgende code gebruiken om een verzoek naar uw web-app te sturen en de time-out van het verzoek te compenseren.
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();
}