webentwicklung-frage-antwort-db.com.de

Wann sollte ich Async-Controller in ASP.NET MVC verwenden?

Ich habe einige Probleme bei der Verwendung von asynchronen Aktionen in ASP.NET MVC. Wann wird die Leistung meiner Apps verbessert und wann nicht?

  1. Ist es sinnvoll, überall in ASP.NET MVC asynchrone Aktionen zu verwenden?
  2. In Bezug auf wartende Methoden: Soll ich asynchrone/wartende Schlüsselwörter verwenden, wenn ich eine Datenbank abfragen möchte (über EF/NHibernate/anderes ORM)?
  3. Wie oft kann ich wait-Schlüsselwörter verwenden, um die Datenbank asynchron in der Methode one single action abzufragen?
197
Vnuuk

Methoden für asynchrone Aktionen sind nützlich, wenn eine Aktion mehrere unabhängige Operationen mit langer Laufzeit ausführen muss.

Eine typische Verwendung für die AsyncController-Klasse sind lang andauernde Webdienstaufrufe.

Sollten meine Datenbankaufrufe asynchron sein?

Der IIS Thread-Pool kann häufig viel mehr gleichzeitige Blockierungsanforderungen verarbeiten als ein Datenbankserver. Wenn die Datenbank der Engpass ist, beschleunigen asynchrone Aufrufe die Datenbankantwort nicht. Ohne einen Drosselmechanismus wird effizient verteilt Mehr Arbeit für einen überlasteten Datenbankserver durch die Verwendung von asynchronen Aufrufen stellt lediglich eine größere Belastung für die Datenbank dar. Wenn Ihre Datenbank der Engpass ist, sind asynchrone Aufrufe kein Wundermittel.

Sie sollten sich 1 und 2 ansehen

Abgeleitet von @PanagiotisKanavos Kommentaren:

Außerdem bedeutet asynchron nicht parallel. Durch die asynchrone Ausführung wird ein wertvoller Threadpool-Thread vom Blockieren für eine externe Ressource befreit, ohne dass Komplexität oder Leistungskosten entstehen. Dies bedeutet, dass derselbe IIS Computer mehr gleichzeitige Anforderungen verarbeiten kann, nicht dass er schneller ausgeführt wird.

Sie sollten auch berücksichtigen, dass das Blockieren von Aufrufen mit einem CPU-intensiven Spinwait beginnt. In Stresszeiten führt das Blockieren von Anrufen zu eskalierenden Verzögerungen und zum Recycling des App-Pools. Asynchrone Aufrufe vermeiden dies einfach

98
Tharif

Sie finden möglicherweise mein MSDN-Artikel zum Thema hilfreich ; In diesem Artikel habe ich viel Platz in Anspruch genommen, umzu beschreiben, wann Sieasync für ASP.NET verwenden sollten, nicht nurwieasync unter ASP.NET verwendet wird.

Ich habe einige Probleme bei der Verwendung von asynchronen Aktionen in ASP.NET MVC. Wann es die Leistung meiner Apps verbessert und wann nicht.

Verstehen Sie zunächst, dass es bei async/await nur umgeht, um Threads freizugeben. Bei GUI-Anwendungen geht es hauptsächlich darum,den GUI-Thread freizugeben, damit die Benutzerfreundlichkeit verbessert wird. Bei Serveranwendungen (einschließlich ASP.NET MVC) geht es hauptsächlich darum,den Anforderungsthread freizugeben, damit der Server skalieren kann.

Insbesondere wirdnicht:

  • Vervollständigen Sie Ihre individuellen Anfragen schneller. In der Tat werden sie langsamer (nur ein kleines bisschen) abgeschlossen.
  • Kehren Sie zum Anrufer/Browser zurück, wenn Sie ein await drücken. await "gibt" nur an den ASP.NET-Thread-Pool, nicht an den Browser.

Die erste Frage ist: Ist es sinnvoll, überall in ASP.NET MVC asynchrone Aktionen auszuführen?

Ich würde sagen, es ist gut, es überall dort einzusetzen, wo Sie I/O machen. Es muss jedoch nicht unbedingtförderlichsein (siehe unten).

Es ist jedoch schlecht , es für CPU-gebundene Methoden zu verwenden. Manchmal denken Entwickler, dass sie die Vorteile von async nutzen können, indem sie Task.Run in ihren Controllern, und das ist eine schreckliche Idee. Da dieser Code letztendlich den Anfragethread freigibt, indem er einen anderen Thread aufnimmt, hat dies überhaupt keinen Vorteil (und tatsächlich werden zusätzliche Thread-Switches bestraft)!

Soll ich beim Abfragen der Datenbank (über EF/NHibernate/andere ORM) async/await-Schlüsselwörter verwenden?

Sie können die erwarteten Methoden verwenden, die Ihnen zur Verfügung stehen. Im Moment unterstützen die meisten Hauptakteure async, aber es gibt einige, die dies nicht tun. Wenn Ihr ORM async nicht unterstützt, versuchen Sie nicht, es in Task.Run oder so etwas (siehe oben).

Beachten Sie, dass ich sagte "Siekönnteverwenden". Wenn Sie über ASP.NET MVC mit einem einzelnen Datenbank-Backend sprechen, werden Sie (mit ziemlicher Sicherheit) keinen Skalierbarkeitsvorteil von async erhalten. Dies liegt daran, dass IIS weitaus mehr gleichzeitige Anforderungen verarbeiten kann als eine einzelne Instanz von SQL Server (oder einem anderen klassischen RDBMS). Wenn Ihr Backend jedoch moderner ist - ein SQL Server-Cluster, Azure SQL, NoSQL usw. - und Ihr Backend kann skaliert werden, und Ihr Skalierbarkeitsengpass ist IIS.dannkönnen Sie einen Skalierbarkeitsvorteil von async erhalten.

Dritte Frage - Wie oft kann ich wait-Schlüsselwörter verwenden, um die Datenbank in EINER einzigen Aktionsmethode asynchron abzufragen?

Beliebig viele. Beachten Sie jedoch, dass viele ORMs eine Regel für eine Operation pro Verbindung haben. Insbesondere erlaubt EF nur eine einzige Operation pro DbContext. Dies gilt unabhängig davon, ob die Operation synchron oder asynchron ist.

Denken Sie auch wieder an die Skalierbarkeit Ihres Backends. Wenn Sie auf eine einzelne Instanz von SQL Server zugreifen und Ihr IIS ist bereits in der Lage, die volle Kapazität von SQL Server beizubehalten, hilft es Ihnen nicht, den Druck auf SQL Server zu verdoppeln oder zu verdreifachen .

214
Stephen Cleary

ist es gut, überall in ASP.NET MVC asynchrone Aktion zu verwenden?

Wie bei der Programmierung üblich, kommt darauf an. Es gibt immer einen Kompromiss, wenn man einen bestimmten Weg einschlägt.

async-await Leuchtet an Stellen, an denen Sie wissen, dass Sie gleichzeitig Anfragen an Ihren Dienst erhalten und in der Lage sein möchten, skalieren gut. Wie hilft async-await Beim Skalieren? In der Tat, wenn Sie einen asynchronen IO call synchron aufrufen, wie z. B. einen Netzwerkaufruf oder einen Treffer in Ihrer Datenbank, den aktuellen Thread, der für die Ausführung verantwortlich ist ist blockiert und wartet auf den Abschluss der Anforderung. Wenn Sie async-await Verwenden, aktivieren Sie das Framework, um eine Zustandsmaschine für Sie zu erstellen, die sicherstellt, dass Ihre Methode nach Abschluss des Aufrufs von IO) dort weiter ausgeführt wird, wo sie aufgehört hat .

Zu beachten ist, dass diese Zustandsmaschine einen subtilen Overhead hat. Eine asynchrone Methode führt nicht zu einer schnelleren Ausführung . Dies ist ein wichtiger Faktor, den viele Menschen verstehen müssen, und ein Missverständnis, das viele Menschen haben.

Eine andere Sache, die bei der Verwendung von async-await Berücksichtigt werden muss, ist die Tatsache, dass es vollständig asynchron ist, was bedeutet, dass Asynchronität Ihren gesamten Aufrufstapel von oben nach unten durchdringt . Dies bedeutet, dass Sie, wenn Sie synchrone APIs verfügbar machen möchten, häufig eine bestimmte Menge an Code duplizieren müssen, da async und sync nicht sehr gut zusammenpassen.

Soll ich beim Abfragen der Datenbank (über EF/NHibernate/andere ORM) async/await-Schlüsselwörter verwenden?

Wenn Sie sich für die Verwendung von asynchronen IO) - Aufrufen entscheiden, dann ist async-await Eine gute Wahl, da immer mehr moderne Datenbankanbieter die asynchrone Methode zur Implementierung von verwenden TAP (Task Asynchronous Pattern).

Wie oft kann ich wait-Schlüsselwörter verwenden, um die Datenbank in EINER einzigen Aktionsmethode asynchron abzufragen?

So viele Sie möchten, solange Sie die von Ihrem Datenbankanbieter festgelegten Regeln einhalten. Die Anzahl der asynchronen Anrufe, die Sie tätigen können, ist unbegrenzt. Wenn Sie voneinander unabhängige und gleichzeitig auszuführende Abfragen haben, können Sie für jede Aufgabe eine neue drehen und mit await Task.WhenAll Warten, bis beide abgeschlossen sind.

19
Yuval Itzchakov

Meine 5 Cent:

  1. Verwenden async/await genau dann, wenn Sie eine IO) - Operation ausführen, z. B. DB oder externer Service-Webservice.
  2. Bevorzugen Sie immer asynchrone Aufrufe an DB.
  3. Jedes Mal, wenn Sie die DB abfragen.

P.S. Es gibt Ausnahmefälle für Punkt 1, aber Sie müssen ein gutes Verständnis für asynchrone Interna haben.

Als zusätzlichen Vorteil können Sie bei Bedarf nur wenige IO Aufrufe parallel ausführen:

Task task1 = FooAsync(); // launch it, but don't wait for result
Task task2 = BarAsync(); // launch bar; now both foo and bar are running
await Task.WhenAll(task1, task2); // this is better in regard to exception handling
// use task1.Result, task2.Result
7

async Aktionen helfen am besten, wenn die Aktionen einige I/O-Operationen für DB oder einige netzwerkgebundene Aufrufe ausführen, bei denen der Thread, der die Anforderung verarbeitet, angehalten wird, bevor er eine Antwort von dem gerade aufgerufenen DB- oder netzwerkgebundenen Aufruf erhält . Am besten verwenden Sie wait mit ihnen und es wird die Reaktionsfähigkeit Ihrer Anwendung wirklich verbessern (weil weniger ASP Eingabe-/Ausgabethreads blockieren, während Sie auf die Datenbank oder einen anderen Vorgang wie diesen warten). In all meinen Anwendungen habe ich immer, wenn viele Aufrufe von DB sehr notwendig waren, diese in eine veränderbare Methode eingebunden und diese mit dem Schlüsselwort await aufgerufen.

6
Dimitri

Wie Sie wissen, unterstützt MVC asynchrone Controller und Sie sollten diese nutzen. Wenn Ihr Controller einen längeren Vorgang ausführt (es kann sich um eine festplattenbasierte E/A oder einen Netzwerkaufruf an einen anderen Remotedienst handeln), wird die IIS Der Thread ist die ganze Zeit beschäftigt, daher wartet der Thread nur auf den Abschluss des langen Vorgangs. Er kann besser genutzt werden, indem andere Anforderungen bearbeitet werden, während der in first angeforderte Vorgang ausgeführt wird. Dies hilft, mehr gleichzeitige Anforderungen zu bearbeiten Ihr Webservice wird hoch skalierbar sein und nicht leicht auf C10k-Problem stoßen. Es ist eine gute Idee, async/await für Datenbankabfragen zu verwenden, und ja, Sie können sie so oft verwenden, wie Sie möchten für fit halten.

Werfen Sie einen Blick auf hier für eine hervorragende Beratung.

4
anurag

Ist es sinnvoll, überall in ASP.NET MVC asynchrone Aktionen zu verwenden?

Dies empfiehlt sich überall dort, wo Sie eine asynchrone Methode verwenden können, insbesondere bei Leistungsproblemen auf Worker-Prozessebene, die bei umfangreichen Daten- und Berechnungsvorgängen auftreten. Andernfalls ist dies nicht erforderlich, da für das Testen von Einheiten ein Casting erforderlich ist.

In Bezug auf wartende Methoden: Soll ich asynchrone/wartende Schlüsselwörter verwenden, wenn ich eine Datenbank abfragen möchte (über EF/NHibernate/anderes ORM)?

Ja, es ist besser, Async für alle DB-Vorgänge zu verwenden, um Leistungsprobleme auf der Ebene der Arbeitsprozesse zu vermeiden. Beachten Sie, dass EF für die meisten Vorgänge viele asynchrone Alternativen erstellt hat, z.

.ToListAsync()
.FirstOrDefaultAsync()
.SaveChangesAsync()
.FindAsync()

Wie oft kann ich wait-Schlüsselwörter verwenden, um die Datenbank in einer einzigen Aktionsmethode asynchron abzufragen?

Der Himmel ist die Grenze

2
Shadi Namrouti

Ich habe die Erfahrung gemacht, dass heutzutage viele Entwickler async/await als Standard für Steuerungen.

Mein Vorschlag wäre, es nur zu verwenden, wenn Sie wissen, dass es Ihnen helfen wird .

Der Grund dafür ist, wie bereits erwähnt, dass Stephen Cleary und andere Probleme mit der Leistung auftreten können, anstatt sie zu lösen. Dies hilft Ihnen nur in einem bestimmten Szenario:

  • Stark frequentierte Controller
  • Skalierbares Backend
1
gajama