2013-04-12 6 views
11

Ich habe vor kurzem an einem Haustier-Projekt in Python mit Kolben gearbeitet. Es ist ein einfacher Pastebin mit serverseitiger Syntax, der die Unterstützung mit Segmenten unterstützt. Da dies eine kostspielige Aufgabe ist, habe ich die Syntaxhervorhebung an eine Sellerie-Aufgabenwarteschlange delegiert, und im Anforderungshandler warte ich darauf, dass sie beendet wird. Unnötig zu sagen, dass dies lediglich die CPU-Nutzung für einen anderen Mitarbeiter verringert, da das Warten auf ein Ergebnis immer noch die Verbindung zum Webserver sperrt. Trotz meiner Instinkte, dass ich eine vorzeitige Optimierung wie die Pest vermeiden sollte, konnte ich mir immer noch nicht helfen, Asynchron zu betrachten.Python asynchrone und CPU-gebundene Aufgaben?

Async

Wenn haben in letzter Zeit Web-Entwicklung wurden folgende Python, Sie haben sicherlich gesehen, dass async überall. Was async ist, bringt kooperatives Multitasking zurück, was bedeutet, dass jeder "Thread" entscheidet, wann und wo er einem anderen nachgibt. Dieser nicht-präventive Prozess ist effizienter als OS-Threads, hat aber immer noch seine Nachteile. Im Augenblick scheint es 2 Hauptansätze zu sein:

  • Ereignis/Rückruf style Multitasking
  • Koroutinen

Die erste stellt concurrency durch lose gekoppelten Komponenten in einer Ereignisschleife ausgeführt. Obwohl dies in Bezug auf Race-Bedingungen sicherer ist und für mehr Konsistenz sorgt, ist es wesentlich weniger intuitiv und schwieriger zu programmieren als präemptives Multitasking.

Die andere ist eine eher traditionelle Lösung, näher am Programmiermodus mit Gewinde, wobei der Programmierer nur den Kontext manuell wechseln muss. Obwohl es anfälliger für Rennen und Deadlocks ist, bietet es eine einfache Drop-In-Lösung.

Die meisten asynchronen Arbeiten werden im Moment an so genannten IO-gebundenen Tasks ausgeführt, Tasks, die auf Eingabe oder Ausgabe warten. Dies wird normalerweise durch die Verwendung von Abruf- und Timeout-basierten Funktionen erreicht, die aufgerufen werden können, und wenn sie negativ zurückkehren, kann der Kontext umgeschaltet werden.

Trotz des Namens könnte dies auf CPU-gebunden Aufgaben auch angewendet werden, die an einen anderen Arbeiter (Thread, Prozess, etc) delegiert werden können und dann non-blockingly warten, um zu ergeben. Idealerweise würden diese Aufgaben auf eine asynchrone Art und Weise geschrieben werden, aber realistisch würde dies bedeuten, dass der Code in ausreichend kleine Blöcke aufgeteilt wird, um nicht zu blockieren, vorzugsweise ohne Kontextschalter nach jeder Codezeile zu streuen. Dies ist insbesondere für existierende synchrone Bibliotheken unbequem.


Aufgrund der Bequemlichkeit, ließ ich mich GEVENT für asynchrones Arbeiten mit und frage mich, wie mit CPU-gebundene Aufgaben in einem Asynchron-Umgebung (mit Futures, Sellerie, etc?) Behandelt werden soll.

Wie verwenden Sie asynchrone Ausführungsmodelle (gevent in diesem Fall) mit herkömmlichen Web-Frameworks wie z. Was sind gängige Lösungen für diese Probleme in Python (Futures, Task Queues)?

EDIT: Um genauer zu sein - Wie gevent mit Kolben zu verwenden und wie mit CPU-gebundenen Aufgaben in diesem Zusammenhang umgehen?

EDIT2: Wenn man bedenkt, wie Python die GIL hat, die die optimale Ausführung von threaded Code verhindert, bleibt nur die Multiprocessing Option, in meinem Fall zumindest.Dies bedeutet, entweder gleichzeitige.Futuren oder einen anderen externen Service zu verwenden Verarbeitung (kann die Türen für sogar etwas Sprache Agnostiker öffnen). Was wären in diesem Fall einige beliebte oder häufig verwendete Lösungen mit gevent (, d. H. Sellerie)? - Best Practices

+0

Sie können dieses Muster in fast jede Bibliothek übernehmen: http://bottlepy.org/docs/dev/async.html#event-callbacks. Ich würde "Evergreen" vorschlagen, weil es die Kombination von kooperativen Aufgaben (Greenlets) mit lang laufenden Aufgaben durch die Integration einer modifizierten Version von 'concurrent.futures' ermöglicht. – schlamar

Antwort

6

Es soll Thread-sicher sein, so etwas wie die folgenden separate CPU-intensive Aufgaben in asynchrone Threads zu tun:

from threading import Thread 

def send_async_email(msg): 
    mail.send(msg) 

def send_email(subject, sender, recipients, text_body, html_body): 
    msg = Message(subject, sender = sender, recipients = recipients) 
    msg.body = text_body 
    msg.html = html_body 
    thr = Thread(target = send_async_email, args = [msg]) 
    thr.start() 

Wenn Sie etwas komplizierter brauchen, dann vielleicht Flask-Sellerie oder Multi Bibliothek mit „Pool "könnte dir nützlich sein.

Ich bin nicht vertraut mit Gevent, obwohl ich mir nicht vorstellen kann, was für mehr Komplexität Sie benötigen oder warum.

Ich meine, wenn Sie versuchen, Effizienz einer großen World-Website zu haben, dann würde ich empfehlen, C++ - Anwendungen zu bauen, um Ihre CPU-intensive Arbeit zu tun, und dann Flask-Sellerie oder Pool verwenden, um diesen Prozess auszuführen. (Das macht YouTube beim Mischen von C++ & Python)

+0

Irgendeine Quelle für wie Youtube tut es (Blogpost oder etwas)? – nikitautiu

+0

Ich endete mit Sellerie, aber wie gesagt, blockiert das Warten auf ein Ergebnis den Webserver. Die Lösung bestand darin, die WSGI-App entweder mit dem Gevent- oder dem Gunicorn-Server mit dem gevent-Worker zu betreiben. Für das asynchrone Ergebnis frage ich einfach 'ready()' ab und wenn nicht, gebe ich mit einem kanonischen 'gevent.sleep()' nach. – nikitautiu

+0

Ich fürchte, ich habe keinen Link, aber der Google Blog könnte ein Ort sein, um danach zu suchen. – Dexter

1

Wie wäre es mit ThreadPool und Queue? Sie können dann Ihre Sachen synchron in einem separaten Thread verarbeiten und Sie müssen sich überhaupt keine Gedanken über das Blockieren machen. Nun, Python ist nicht für CPU-gebundene Aufgaben geeignet, also sollten Sie auch daran denken, Subprozesse hervorzubringen.

+0

Das ist eine gültige Lösung, und es gibt ein paar andere, an die ich denken könnte. Der Punkt ist, ich habe mich gefragt, wie man gevent in flash integriert und wie Leute, die gevent benutzen, mit Situationen umgehen, in denen es unmöglich ist, eine synchrone Aufgabe "grün" zu machen. – nikitautiu

Verwandte Themen