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?
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:
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:
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:
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:
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.
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.
Tags und Links python asynchronous tornado