Et par tusinde anmodninger i minuttet er en stor load, og den eneste måde at gøre det rigtigt på, er ved at kontrollere og begrænse det maksimale antal tråde, der kan køre på ethvert tidspunkt.
Da der ikke er meget information om, hvordan du har implementeret dette. Jeg vil dække et par mulige omstændigheder.
Tid til at eksperimentere...
Konstanterne:
- Elementer, der skal behandles:
- 50 pr. sekund , eller med andre ord...
- 3.000 i minuttet , og endnu en måde at se det på...
- 180.000 i timen
Variablerne:
-
Dataoverførselshastigheder:
-
Hvor meget data du kan overføre pr. sekund kommer til at spille en rolle, uanset hvad vi gør, og dette vil variere i løbet af dagen afhængigt af tidspunktet på dagen.
Det eneste, vi kan gøre, er at affyre flere anmodninger fra forskellige cpu'er for at fordele vægten af trafik, vi sender tilbage.
-
-
Behandlingskraft:
-
Jeg går ud fra, at du har dette i et
WebJob
i modsætning til at have dette kodet inde på MVC-stedet, det er sig selv. Det er meget ineffektivt og passer ikke til det formål, du forsøger at opnå. Ved at bruge et WebJob kan vi kø arbejdsemner, der skal behandles af andreWebJobs
. køen det drejer sig om Azure Queue Opbevaring .
-
Problemerne:
- Vi forsøger at gennemføre 50 transaktioner i sekundet, så hver transaktion skulle udføres på under 1 sekund, hvis vi brugte 50 tråde. Vores 45 sekunders time-out tjener intet formål på nuværende tidspunkt.
- Vi forventer, at 50 tråde kører samtidigt, og alle færdiggøres på under et sekund, hvert sekund, på en enkelt cpu. (Jeg overdriver en pointe her, bare for at gøre en pointe... men forestil dig at downloade 50 tekstfiler hvert eneste sekund. Bearbejde det og derefter prøve at skyde det tilbage til en kollega i håb om, at de endda vil være klar til at fange det)
- Vi skal have en genforsøgslogik på plads, hvis varen efter 3 forsøg ikke er behandlet, skal den sættes tilbage i køen. Ideelt set skulle vi give serveren mere tid til at reagere end blot et sekund med hver fejl, lad os sige, at vi gav den en pause på 2 sekunder ved første fejl, derefter 4 sekunder, derefter 10, dette vil i høj grad øge chancerne for, at vi fortsætter / at hente de data, vi havde brug for.
- Vi antager at vores MongoDb kan håndtere dette antal anmodninger pr. sekund. Hvis du ikke allerede har gjort det, så begynd at se på måder at skalere det ud på, problemet er ikke det faktum, at det er en MongoDb, datalaget kunne have været hvad som helst, det er det faktum, at vi laver dette antal anmodninger fra en enkelt kilde, der vil være den mest sandsynlige årsag til dine problemer.
Løsningen:
- Opret en
WebJob
og navngiv denEnqueueJob
. DenneWebJob
vil have ét eneste formål, at sætte arbejdsemner i kø, der skal behandles iQueue Storage
. - Opret en
Queue Storage Container
navngivetWorkItemQueue
, vil denne kø fungere som en trigger til næste trin og sætte gang i vores udskaleringsoperationer. - Opret endnu et
WebJob
navngivetDequeueJob
. DenneWebJob
vil også have ét eneste formål, at bringe arbejdsemnerne i kø fraWorkItemQueue
og affyr anmodningerne til dit datalager. - Konfigurer
DequeueJob
at spinne op, når et emne er blevet placeret inde iWorkItemQueue
, start 5 separate tråde på hver og mens køen ikke er tom, sæt arbejdsemner i kø for hver tråd og forsøg at udføre det udsatte job.- Forsøg 1, hvis det mislykkes, vent og prøv igen.
- Forsøg 2, hvis det mislykkes, vent og prøv igen.
- Forsøg 3, hvis det mislykkes, kør elementet tilbage til
WorkItemQueue
- Konfigurer dit websted til automatisk at skalere ud til x antal cpu'er (bemærk, at dit websted og dine webjobs deler de samme ressourcer)
Her er en kort 10 minutters video der giver et overblik over, hvordan man bruger kølagring og webjobs.
Rediger:
En anden grund til, at du muligvis får disse fejl, kan også være på grund af to andre faktorer, igen forårsaget af, at det er i en MVC-app...
Hvis du kompilerer programmet med DEBUG
attribut anvendt, men skubber RELEASE
version i stedet, kan du løbe ind i problemer på grund af indstillingerne i din web.config
, uden DEBUG
attribut, vil en ASP.NET webapplikation køre en anmodning i maksimalt 90 sekunder, hvis anmodningen tager længere tid end dette, vil den bortskaffe anmodningen.
For at øge timeoutet til længere end 90 sekunder du bliver nødt til at ændre [httpRuntime][3]
ejendom i din web.config
...
<!-- Increase timeout to five minutes -->
<httpRuntime executionTimeout="300" />
Den anden ting, du skal være opmærksom på, er indstillingerne for anmodningstimeout i din browser> webapp, jeg vil sige, at hvis du insisterer på at beholde koden i MVC i modsætning til at udtrække den og sætte den ind i et WebJob, så kan bruge følgende kode til at sende en anmodning til din webapp og udligne timeoutet for anmodningen.
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();
}