Django lange laufende asynchrone Aufgaben mit Threads / Verarbeitung
Haftungsausschluss: ich weiß, dass es mehrere ähnliche Fragen auf, SO. Ich glaube, ich habe gelesen, die meisten, wenn nicht alle von Ihnen, aber nicht eine Antwort finden auf meine eigentliche Frage (siehe später).
Auch ich weiß, dass die Verwendung von Sellerie oder anderen asynchronen queue-Systemen ist der beste Weg, um eine lange laufende Aufgaben - oder zumindest verwenden Sie einen cron-Skript verwaltet. Es gibt auch mod_wsgi doc über Prozesse und threads aber ich bin mir nicht sicher, ob ich alles richtig.
Die Frage ist:
was sind die genauen Risiken/Probleme mit der Verwendung der unten aufgeführten Lösungen gibt es? Einer von Ihnen rentabel für die lange laufende Aufgaben (ok, auch wenn Sellerie ist besser geeignet)?
Meine Frage ist eigentlich mehr Verständnis über die Interna von wsgi und python/django, als die Suche nach der besten Gesamtlösung. Probleme mit blockieren von threads, unsichere Zugriff auf Variablen, zombie, Verarbeitung, etc.
Sagen wir mal:
- meine "long_process" ist etwas wirklich sicher. auch wenn es nicht das ist mir egal.
- python >= 2.6
- Ich bin mit mod_wsgi im apache (wird nichts ändern mit uwsgi gunicorn oder?) im daemon-Modus
mod_wsgi conf:
WSGIDaemonProcess NAME user=www-data group=www-data threads=25
WSGIScriptAlias //path/to/wsgi.py
WSGIProcessGroup %{ENV:VHOST}
Dachte ich, dies sind die verfügbaren Optionen zum starten von separaten Prozesse (gemeint im weitesten Sinne) zu tragen, die auf eine lange andauernde Aufgabe während der Rückkehr schnell eine Antwort an den Benutzer:
os.Gabel
import os
if os.fork()==0:
long_process()
else:
return HttpResponse()
Teilprozess
import subprocess
p = subprocess.Popen([sys.executable, '/path/to/script.py'],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
(wo das Skript ist wahrscheinlich ein manage.py Befehl)
threads
import threading
t = threading.Thread(target=long_process,
args=args,
kwargs=kwargs)
t.setDaemon(True)
t.start()
return HttpResponse()
NB.
Aufgrund des Global Interpreter Lock, in CPython nur ein thread ausgeführt werden können Python-code auf einmal (auch wenn bestimmte performance-orientierte Bibliotheken könnte diese Einschränkung zu überwinden). Wenn Sie möchten, dass Ihre Anwendung zu einer besseren Nutzung der Rechenleistung von multi-core-Maschinen, die Sie verwenden sollten, die multiprocessing. Jedoch wird der Durchzug noch ein geeignetes Modell, wenn Sie mehrere I/O-bound tasks gleichzeitig.
Den Haupt-thread, schnell zurück (httpresponse). Wird die erzeugte langen thread block wsgi zu tun, etwas anderes für eine andere Anfrage?!
multiprocessing
from multiprocessing import Process
p = Process(target=_bulk_action,args=(action,objs))
p.start()
return HttpResponse()
Diese lösen sollte der thread-concurrency-Problem, sollte es nicht?
Also das sind die Optionen, die ich denken konnte. Was funktionieren würde und was nicht, und warum?
InformationsquelleAutor der Frage Stefano | 2011-11-09
Du musst angemeldet sein, um einen Kommentar abzugeben.
os.Gabel
Einer Gabel Klon der übergeordnete Prozess, der in diesem Fall, ist Ihre Django-stack. Da Sie ja nur zu wollen, führen Sie eine separate python-Skript, das scheint wie eine unnötige Menge an aufblasen.
Teilprozess
Mit
subprocess
erwartet wird, interaktiv zu sein. In anderen Worten, während Sie können dies nutzen, um effektiv spawn einen Prozess in Gang, es ist zu erwarten, dass irgendwann werden Sie es zu beenden, wenn Sie fertig sind. Es ist möglich, Python könnte bereinigen für Sie, wenn Sie lassen Sie einen laufen, aber meine Vermutung wäre, dass diese tatsächlich ein memory leak.threads
Threads sind definierte Einheiten der Logik. Beginnen Sie, wenn Ihre
run()
- Methode aufgerufen wird, und beendet, wenn dierun()
Methode der Ausführung endet. Das macht Sie gut geeignet, um zu erstellen ein Zweig der Logik, die ausgeführt wird, außerhalb des aktuellen Bereichs. Jedoch, wie Sie bereits erwähnt, unterliegen Sie der Global Interpreter Lock.multiprocessing
Dies ist im Grunde threads auf Steroiden. Es hat die Vorteile eines Threads, aber unterliegt nicht dem Global Interpreter Lock, und können die Vorteile von multi-core-Architekturen. Allerdings sind Sie schwieriger zu arbeiten, als ein Ergebnis.
So, Ihre Entscheidungen wirklich nach unten kommen, um die Fäden oder multiprocessing. Wenn Sie können, kommen mit einem thread und es macht Sinn, für Ihre Anwendung, gehen Sie mit einem Faden. Andernfalls verwenden Sie multiprocessing.
InformationsquelleAutor der Antwort Chris Pratt
Habe ich festgestellt, dass mit uWSGI Dekorateure ist ganz einfacher als die Verwendung von Sellerie, wenn Sie benötigen, führen Sie einfach einige tasks im hintergrund.
Denke, dass Sellerie ist beste Lösung für schwere schwere Projekt, und es ist overhead für etwas einfach.
Für start mit uWSGI Dekorateure müssen Sie nur aktualisieren Sie Ihre uWSGI config mit
code schreiben wie:
Als beim start anzeigen im uWSGI log erscheint:
und wenn die Aufgabe beendet:
Es ist seltsam(für mich) Einschränkungen:
InformationsquelleAutor der Antwort Oleg Neumyvakin
Für die Frage:
die Antwort ist Nein.
Haben Sie noch zu werden sorgfältige erstellen von hintergrund-threads-Antrag, obwohl in dem Fall erstellen Sie einfach eine riesige Anzahl von Ihnen und verstopfen den gesamten Prozess. Sie wirklich brauchen, eine Aufgabe queueing-system, auch wenn Sie Dinge tun, in den Prozess.
In Respekt zu tun, eine fork oder exec von web-Prozess, insbesondere Apache, ist in der Regel nicht eine gute Idee, da kann der Apache möglicherweise verhängen ungerade Bedingungen auf die Umwelt in der sub-Prozess erstellt, das konnte technisch nicht mit Ihrer operation.
Mit einem system wie Sellerie ist wohl noch die beste Lösung.
InformationsquelleAutor der Antwort Graham Dumpleton