Korrekte Verwendung von await-async in webapi
Ich habe eine WebApi, dass für jede eingehende Anfrage, Anrufe, 2 separate webservices, führt einige post-processing und gibt die Ergebnisse zurück.
Den ersten webservice-Aufruf wird lokal zwischengespeichert, für 1 Stunde, und die Daten in diese bestimmt die Abfrage, auf der 2. webservice. Der 2. webservice aufgerufen wird, auf jede eingehende Anfrage. Nach der 2. Anfrage gemacht, jedes Ergebnis ist verarbeitet mit business-Logik und kehrte zurück, um die client-Antwort.
Dem Aufruf der 2. webservice nicht asynchron, da eine 3rd-party-dll, die nicht zulässt, dass der await-Schlüsselwort. Was ich getan habe, gewickelt ist, der 2. webservice-Aufruf und die Nachbearbeitung in eine async-Funktion, die aufgerufen wird, von der Steuereinheit.
///api/controller/news?key=a&state=b
public async Task<HttpResponseMessage> GetNews(string key, string state)
{
//call to first webservice if not in cache
if (JsonConfig != null && JsonConfig.Configuration.NewsQuery.ContainsKey(key))
{
var results = await SearchProxyProvider.Search(filters.All, filters.Any, filters.None, filters.Sort, 100, 0, true, state, true);
int totalCount = results.TotalCount;
return Request.CreateResponse(HttpStatusCode.OK, results);
}
}
//Helper class method
public async Task<ItemCollection<Item>> Search(List<FieldValuePair> allFilters, List<FieldValuePair> anyFilters, List<FieldValuePair> noneFilters, SortedFieldDictionary sortBy, int pageSize = 100, int pageNumber = 0, bool exact = true, string stateFilter = null, bool getAllResults = true)
{
//call to 2nd api
search = SomeApi.Search(allFilters, anyFilters, noneFilters, pageSize, pageNumber, exact,
sortBy, null, WebApiConstant.Settings.CustomFields, true);
//post processing on search results
return search;
}
Da der Aufruf der ersten webservice wird lokal zwischengespeichert, sehe ich nicht wirklich ein großer Vorteil, dass diese asynchron.
Ich bin gerade auf der Suche um zu sehen, ob dieser Ansatz Total falsch ist, oder richtig.
- Wie viele Aufrufe an web-api erwarten Sie, dass pro Stunde im Durchschnitt?
- Blick auf 1000 gleichzeitige Benutzer. Es werden mehrere Server load-balancing der webapi, 2-3. Eine erste Anwendung der download von 400K Benutzer erwartet wird.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie einige tricks mit
AsyncLazy<T>
(z.B., aus meinem blog) und cache, statt. Das gibt Ihre Anfragen ein Weg, um (asynchron) warten Sie auf eine Aktualisierung, und Sie nicht schlagen Service1 mehrere Male, wenn Sie brauchen, um die Daten zu aktualisieren, unabhängig von der Anzahl der gleichzeitigen Anfragen.Das ist ein Mist. Tun auf Sie stützen, um es zu beheben. 🙂
Gibt ' s keinen Punkt zu. Der compiler warnt Sie, dass Ihr "async" - Methode ist in der Tat synchron.
Wenn es synchron ist, dann nenne es einfach synchron. Auf der server-Seite, es gibt keinen Punkt, den Umschlag in
Task.Run
oder etwas ähnliches.Habe ich einige Folien aus einer "Async" auf dem Server" sprechen gab ich Montag bei ThatConference, die Sie vielleicht nützlich finden. (Sie haben Animationen, wie asynchrone requests behandelt werden und warum "fake asynchrone" Methoden nicht helfen, die auf der server-Seite).
Task.Run
, aber das wird nicht gewinnen Sie nichts. Der gesamte Punktasync
im WebAPI ist auf reduzieren die Anzahl der threads, so dass Sie nicht wollen, um die Warteschlange Arbeit an den thread-pool überhaupt. Wenn diese Erklärung nicht klar ist, dann denke über die Antwort auf diese Frage: Warum kann ich wollen zu machen, es asynchron?async
auf der server-Seite. Es ist eine große video auf Channel9, aber andere als, dass die besten Ressourcen, die ich kenne, meinen eigenen blog und slide-deck (hoffentlich werde ich sein posting video in ein paar Wochen).Machen Funktion Suchen wirklich async-Aufruf SomeApi.Suche gewickelt werden kann in eine separate Aufgabe, und dann erwartete. Auch wrappen der code in der ersten Funktion in einer Aufgabe, mit Ihrem laden schätzt cache-Validierung möglicherweise auch ein Engpass.
Task.Run
ist besser alsStartNew
fürasync
code.async
ist freie worker-threads, und wenn Sie zu befreien, bis ein worker-thread durch queueing-Arbeit an den thread-pool (werden ausgeführt, indem ein weiterer worker-thread), gewinnen Sie nichts. OTOH, ist dies eine nützliche Technik fürasync
Sie auf den client, denn der Punkt, es ist die UE thread. So können Sie die Warteschlange, bis die Arbeit an den thread-pool-und das ist in Ordnung so, weil es nicht im UI-thread ausgeführt.Task.Run
ist bevorzugt überTaskFactory.StartNew
fürasync
code. Hier ist der Grund, warum." Aber "besser" ist nicht falsch. Das problem mitStartNew
ist, dass es so einfach zu bedienen ist falsch, z.B. zu vergessen, denTaskScheduler
argument (das sollte immer angegeben werden - einige details sind in Stephen Toub blog-post).