2009-05-12 10 views
5

Ich arbeite an einer Django-Anwendung, die es einem Benutzer ermöglicht, Dateien hochzuladen. Ich muss einige serverseitige Verarbeitung für diese Dateien durchführen, bevor Sie sie an Amazon S3 senden. Nach dem Lesen der Antworten auf this question und this blog post entschied ich, dass die beste Art und Weise, um dies zu behandeln ist, meine View-Handler eine Methode auf Pyro Remote-Objekt aufrufen, um die Verarbeitung asynchron durchzuführen und dann sofort eine HTTP 200 an den Client zurückgeben. Ich habe diesen Prototyp und es scheint gut zu funktionieren, jedoch möchte ich auch den Status der Verarbeitung speichern, so dass der Client die Anwendung abfragen kann, um zu sehen, ob die Datei verarbeitet und auf S3 hochgeladen wurde.Wie sollte ich den Status für einen lang andauernden Prozess speichern, der von Django aufgerufen wird?

Ich kann die Abfrage einfach genug handhaben, aber ich bin nicht sicher, wo der entsprechende Speicherort den Prozessstatus speichern soll. Es muss durch den Pyro-Prozess beschreibbar und in meiner Abfrageansicht lesbar sein.

  • Ich zögere, Spalten zur Datenbank hinzuzufügen, die eigentlich nur für 30 bis 60 Sekunden bestehen sollten.
  • Ich habe überlegt low-level cache API von Django zu verwenden und eine Datei-ID als Schlüssel zu verwenden, aber ich glaube nicht, dass dies wirklich das ist, wofür das Cache-Framework entworfen wurde und ich bin mir nicht sicher, welche unvorhergesehenen Probleme es dabei geben könnte Route.
  • Zuletzt habe ich überlegt, den Status in dem Pyro-Objekt zu speichern, das die Verarbeitung ausführt, aber dann scheint es, als ob ich eine boolesche "processing_complete" Datenbankspalte hinzufügen müsste, damit die Ansicht weiß, ob Status vom Pyro abgefragt werden soll Objekt.
  • Natürlich gibt es auch einige Bedenken hinsichtlich der Datenintegrität beim Entkoppeln des Zustands von der Datenbank (was passiert, wenn der Server ausfällt und alle diese Daten im Speicher sind?). Ich bin zu hören, wie erfahrenere Webanwendungsentwickler mit dieser Art von Stateful Processing umgehen würden.

    Antwort

    6

    Wir tun dies, indem wir eine "Anfrage" -Tabelle in der Datenbank haben.

    Wenn der Upload ankommt, erstellen wir das hochgeladene File-Objekt und erstellen eine Anfrage.

    Wir starten den Hintergrund Batch-Prozessor.

    Wir geben eine 200 "Wir arbeiten daran" Seite zurück - sie zeigt die Anfragen und ihren Status.

    Unser Stapelprozessor verwendet das Django ORM. Wenn es fertig ist, aktualisiert es das Request-Objekt. Wir können (aber nicht) eine E-Mail-Benachrichtigung senden. Meistens aktualisieren wir nur den Status, damit sich der Benutzer erneut anmelden kann und sehen, dass die Verarbeitung abgeschlossen ist.


    Batch-Server-Architektur Notizen.

    Es handelt sich um einen WSGI-Server, der auf einen Port für eine Stapelverarbeitungsanforderung wartet. Die Anfrage ist ein REST POST mit einer ID-Nummer; Der Batch-Prozessor sieht dies in der Datenbank nach und verarbeitet sie.

    Der Server wird automatisch von unserer REST-Schnittstelle gestartet. Wenn es nicht läuft, spawnen wir es. Das lässt eine Benutzertransaktion langsam erscheinen, aber naja. Es soll nicht abstürzen.

    Außerdem haben wir eine einfache crontab, um zu überprüfen, dass es läuft. Es wird höchstens 30 Minuten dauern zwischen "Bist du am Leben?" Kontrollen.Wir haben kein formales Startskript (wir laufen unter Apache mit mod_wsgi), aber wir können ein "Neustart" -Skript erstellen, das die WSGI-Datei berührt und dann einen POST an eine URL durchführt, die eine Integritätsprüfung durchführt (und die Stapelverarbeitung).

    Wenn der Batch-Server gestartet wird, kann es unverarbeitete Anforderungen geben, für die er nie einen POST erhalten hat. Der Standardstart besteht also darin, ALLES aus der Anforderungswarteschlange zu ziehen - vorausgesetzt, es ist möglicherweise etwas verpasst worden.

    +0

    Nachdem ich über Nacht darüber nachgedacht habe, habe ich entschieden, dass Sie absolut Recht haben. Es macht einfach keinen Sinn, die Datenbank nicht zu benutzen. Ich habe auch entschieden, dass Pyro hier schlecht passt und dass ich einfach tun sollte, was normale Leute machen und einen Cron-Job mit einer Sperrdatei verwenden. – bouvard

    +0

    Wir verwenden nicht Cron. Wir haben unser Batch-System als kleinen WSGI-Server und wir machen eine HTTP-Anfrage mit urllib2, um es zu wecken. Er erhält die Request-ID von der WSGI-Anfrage; bekommt die Details mit gewöhnlichem Django ORM. –

    +0

    Das ist etwas, was ich mit Pyro geplant habe, aber das Problem, das ich vorhersehe, ist, dass ein plötzlicher Serverausfall die Dokumente zur Hälfte verarbeitete und es keine neue Anforderungsnachricht geben würde, um die Verarbeitung erneut zu initiieren. Wenn ich einen Cron-Job verwende, weiß ich, dass ich einfach die alten 10 unfertigen Jobs aus der Anfrage-Tabelle auswählen kann, und ich werde jeden abholen, der während des Ausfalls abgeschnitten wurde. – bouvard

    1

    Also, es ist eine Job-Warteschlange, die Sie brauchen. Für Ihren Fall würde ich unbedingt mit der DB gehen, um den Staat zu retten, auch wenn diese Staaten kurzlebig sind. Es hört sich so an, als würde es all Ihre Anforderungen erfüllen und ist nicht so schwer zu implementieren, da Sie bereits alle beweglichen Teile für sich haben. Halten Sie es einfach, es sei denn Sie brauchen etwas komplexer.

    Wenn Sie etwas stärkeres oder anspruchsvolleres benötigen, würde ich etwas wie Gearman betrachten.

    5

    Ich weiß, das ist eine alte Frage, aber jemand kann meine Antwort auch nach all dieser Zeit nützlich finden, also hier geht es.

    Sie können natürlich Datenbank als Warteschlange verwenden, aber es gibt Lösungen, die genau für diesen Zweck entwickelt wurden.

    AMQP ist nur dafür gemacht. Zusammen mit oder Carrot und einem Broker-Server wie RabbitMQ oder ZeroMQ.

    Das ist, was wir in unserem neuesten Projekt verwenden und es funktioniert großartig.

    Für Ihr Problem Sellerie und RabbitMQ scheint wie eine beste Passform. RabbitMQ bietet Persistenz Ihrer Nachrichten, und Sellery stellt einfache Ansichten für die Abfrage zur Verfügung, um den Status paralleler Prozesse zu überprüfen.

    Sie könnten auch interessiert sein an octopy.