2014-06-11 12 views
11

Da Netty ein nicht blockierender Server ist, welcher Effekt ändert eine Aktion auf .async?Welchen Effekt hat die Verwendung von Action.async, da Play Netty verwendet, das nicht blockierend ist

def index = Action { ... } 

gegen

def index = Action.async { ... } 

Ich verstehe, dass mit .async Sie Future[SimpleResult] bekommen. Aber da Netty nicht blockierend ist, wird Play irgendetwas Ähnliches unter den Deckeln tun?

Welchen Einfluss hat dies auf Durchsatz/Skalierbarkeit? Ist das eine schwierige Frage, wo es auf andere Faktoren ankommt?

Der Grund ich frage, ich habe meine eigene benutzerdefinierte Action und ich wollte das Cookie-Timeout für jede Anfrage zurücksetzen, damit ich dies tue, die ein async Anruf:

object MyAction extends ActionBuilder[abc123] { 
    def invokeBlock[A](request: Request[A], block: (abc123[A]) => Future[SimpleResult]) = { 
    ... 
    val result: Future[SimpleResult] = block(new abc123(..., result)) 
    result.map(_.withCookies(...)) 
    } 
} 

Die wegnehmen von der oben genannten Schnipsel ist ich mit einem Future[SimpleResult], ist dies ähnlich zu rufen Action.async, aber das ist innerhalb meiner Aktion selbst?

Ich möchte verstehen, welche Auswirkungen dies auf mein Anwendungsdesign haben wird. Es scheint nur für die Fähigkeit zu sein, meinen Cookie pro Anfrage zu setzen, ich habe von blockierend zu nicht-blockierend geändert. Aber ich bin verwirrt, seit Netty nicht blockiert, vielleicht habe ich wirklich nichts in der Realität verändert, da es bereits asynchron war?

Oder habe ich einfach einen anderen asynchronen Anruf in einem anderen eingebettet?

In der Hoffnung, jemand kann dies mit einigen Details und wie oder was dies in Leistung/Durchsatz haben wird klären.

Antwort

18

def index = Action { ... } ist nicht blockierend Sie haben Recht.

Der Zweck von Action.async ist einfach zu erleichtern, mit Futures in Ihren Aktionen zu arbeiten.

Zum Beispiel:

def index = Action.async { 
    val allOptionsFuture: Future[List[UserOption]] = optionService.findAll() 
    allOptionFuture map { 
    options => 
     Ok(views.html.main(options)) 
    } 
} 

Hier mein Dienst gibt ein Future und Umgang zu vermeiden, mit dem Ergebnis, Extrahieren I Karte nur es eine zu Future[SimpleResult] und Action.async kümmert sich um den Rest.

Wenn mein Dienst List[UserOption] direkt zurückgab, konnte ich einfach Action.apply verwenden, aber unter der Haube würde es immer noch nicht blockierend sein.

Wenn man sich Action Quellcode, können Sie sogar sehen, dass apply schließlich ruft async: https://github.com/playframework/playframework/blob/2.3.x/framework/src/play/src/main/scala/play/api/mvc/Action.scala#L432

+0

ich sehe, so in meinem "MyAction", was ist der Nettoeffekt der Verwendung von mir mit einer Zukunft und callinf result.map? Und was, wenn ich Myaction.async in meinem Controller mache? (im Vergleich zur Verwendung der Standardaktion) – Blankman

+1

Nun, ich dachte, ich hätte deine Frage beantwortet. Sie sollten sich diese Seite der Dokumentation ansehen: http://www.playframework.com/documentation/2.3.x/ScalaAsync – vptheron

+1

Danke, ich habe das früher gelesen. Eine Zukunft zu haben, die eine Zukunft nennt usw. wirkt sich nicht wirklich auf die Leistung aus? – Blankman

0

ich auf diese Frage kommen passiert, Ich mag die Antwort von @vptheron, und ich möchte auch teilen etwas, was ich aus dem Buch "Reactive Web Applications" gelesen habe, was meiner Meinung nach auch großartig ist.

Der Builder Action.async erwartet eine Funktion des Typs Request => Future[Result]. Auf diese Weise deklarierte Aktionen unterscheiden sich nicht wesentlich von normalen Aufrufen Action { request => ... }. Der einzige Unterschied besteht darin, dass Play weiß, dass die Aktionen Action.async bereits asynchron sind, sodass sie ihren Inhalt nicht in einen zukünftigen Block einbinden.

Das ist richtig - Play plant standardmäßig, dass ein Action-Body asynchron mit seinem Standard-Web-Worker-Pool ausgeführt wird, indem die Ausführung in einer Zukunft verpackt wird. Der einzige Unterschied zwischen Action und Action.async besteht darin, dass wir im zweiten Fall eine asynchrone Berechnung durchführen.

Es stellte auch eine Probe:

def listFiles = Action { implicit request => 
    val files = new java.io.File(".").listFiles 
    Ok(files.map(_.getName).mkString(", ")) 
} 

die gegeben problematisch, seine Verwendung des Blockier java.io.File API ist.

Hier ist die java.io.File API eine Blockierung I/O-Operation durchführt, was bedeutet, dass eines der wenigen Themen von Web-Arbeiter Becken Das Spiel wird aus der Liste der Dateien in dem Ausführungsverzeichnis, während die OS Zahlen entführt werden. Dies ist die Situation, die Sie unbedingt vermeiden sollten, da der Worker-Pool möglicherweise keine Threads mehr aufweist.

-

Das reaktive Audit-Tool, zielt darauf ab, verfügbar bei https://github.com/octo-online/reactive-audit, in einem Projekt blockiert Anrufe zu hinweisen.

Hoffe es hilft auch.

Verwandte Themen