Einfaches asynchrones Beispiel mit Tornado-Python

8

Ich möchte ein einfaches asynchrones Serverbeispiel finden. Ich habe eine Funktion mit viel warten, Datenbanktransaktionen ... etc:

%Vor%

Ich muss es Funktion in getrennten Prozess ausführen, ohne zu blockieren. Ist es möglich?

    
user1941407 07.04.2014, 19:05
quelle

3 Antworten

16

Tornado wurde entwickelt, um alle Ihre Operationen in einem einzigen Thread auszuführen, verwendet jedoch asynchrone I / O, um eine Blockierung so weit wie möglich zu vermeiden. Wenn die von Ihnen verwendete Datenbank asynchrone Python-Bindungen hat (im Idealfall speziell für Tornado, wie Motor für MongoDB oder < a href="https://github.com/FSX/momoko"> momoko für Postgres), dann können Sie Ihre DB-Abfragen ausführen, ohne den Server zu blockieren. keine separaten Prozesse oder Threads benötigt.

Um das genaue Beispiel anzugeben, das Sie angegeben haben und in dem time.sleep(1) aufgerufen wird, können Sie diesen Ansatz asynchron über Tornado-Korutinen verwenden:

%Vor%

Der interessante Teil ist async_sleep . Diese Methode erstellt eine asynchrone Task, die die Methode ioloop.add_timeout aufruft. add_timeout wird nach einer bestimmten Anzahl von Sekunden einen bestimmten Callback ausführen, ohne den ioloop zu blockieren, während er darauf wartet, dass das Timeout abläuft. Es erwartet zwei Argumente:

%Vor%

Wie Sie im obigen Beispiel sehen können, stellen wir nur einen Parameter für add_timeout explizit im Code zur Verfügung, was bedeutet, dass wir dies folgendermaßen erreichen:

%Vor%

Wir bieten den erwarteten Rückrufparameter nicht an. Wenn gen.Task add_timeout ausführt, fügt es tatsächlich ein callback Schlüsselwortargument an das Ende der explizit angegebenen Parameter an. Also das:

%Vor%

Ergebnisse, die in gen.Task () ausgeführt werden:

%Vor%

Wenn gen.Callback nach dem Timeout ausgeführt wird, zeigt dies an, dass gen.Task abgeschlossen ist, und die Programmausführung wird mit der nächsten Zeile fortgesetzt. Dieser Fluss ist irgendwie schwer zu verstehen, zumindest auf den ersten Blick (es war sicherlich für mich, als ich das erste Mal darüber las). Es wird wahrscheinlich hilfreich sein, die Tornado-Modul-Dokumentation ein paar Mal zu lesen.

    
dano 08.04.2014 20:42
quelle
4
%Vor%

Wenn Sie über dem Code laufen, können Sie einen rechenintensiven Vorgang bei Ссылка ausführen, der die Ausführung nicht blockiert, siehe Besuch Ссылка gleich nach dem Besuch von Ссылка .

    
Iaroslav 07.09.2016 22:52
quelle
0

Hier aktualisiere ich die Informationen über Tornado 5.0. Tornado 5.0 fügen Sie eine neue Methode IOLoop.run_in_executor hinzu. In den "Calling Blocking-Funktionen" von Coroutine-Mustern Kapitel:

  

Die einfachste Methode zum Aufrufen einer blockierenden Funktion aus einer Coroutine besteht in der Verwendung von IOLoop.run_in_executor, der Futures zurückgibt, die mit Coroutinen kompatibel sind:

     

@gen.coroutine def call_blocking(): yield IOLoop.current().run_in_executor(blocking_func, args)

Auch im Dokument run_on_executor , heißt es :

  

Dieser Dekorator sollte nicht mit dem gleichnamigen IOLoop.run_in_executor verwechselt werden. Im Allgemeinen wird empfohlen, run_in_executor beim Aufrufen einer Blockierungsmethode zu verwenden, anstatt diesen Dekorator beim Definieren einer Methode zu verwenden. Wenn die Kompatibilität mit älteren Versionen von Tornado erforderlich ist, sollten Sie einen Executor definieren und am Aufrufstandort executor.submit () verwenden.

In Version 5.0 wird IOLoop.run_in_executor im Anwendungsfall von Calling blocking functions empfohlen.

    
Qianyue 08.03.2018 06:21
quelle

Tags und Links