Job-Verarbeitung über Web-Anwendung: Echtzeit-Status-Updates und Back-End-Messaging

8

Ich möchte eine (Open-Source-) Webanwendung implementieren, bei der der Benutzer eine Art Anfrage über seinen Browser an eine Python-Webanwendung sendet. Die Anfragedaten werden verwendet, um eine Art von Heavy-Computing-Job zu definieren und einzureichen. Computer-Jobs werden in ein "Worker-Backend" (auch Python) ausgelagert. Während der Jobverarbeitung durchläuft der Job im Laufe der Zeit verschiedene Phasen (von "übergeben" über Zwischenzustände bis "fertig", idealerweise). Was ich erreichen möchte, ist, den aktuellen Jobstatus dem Benutzer in Echtzeit anzuzeigen. Dies bedeutet, dass das Worker-Backend Job-Status an die Webanwendung zurückmelden muss. Die Webanwendung muss dann Informationen an den Browser des Benutzers senden. Ich habe ein Bild für dich mitgebracht, das schematisch die Grundidee beschreibt:

Die Zahlen in roten Kreisen zeigen die chronologische Reihenfolge der Ereignisse an. "Web App" und "Worker Backend" sind noch zu entwickeln. Nun, ich wäre dankbar, wenn Sie mir bei einigen Technologieentscheidungen helfen könnten.

Meine Fragen, insbesondere:

  1. Welche Messaging-Technologie sollte ich zwischen Web-App und Worker-Backend anwenden? Wenn das Worker-Back-End ein Signal (eine Nachricht irgendeiner Art) über einen bestimmten Job sendet, muss es ein Ereignis in der Web-Anwendung auslösen. Daher benötige ich eine Art Callback, das dem Client zugeordnet ist, der ursprünglich die Jobübermittlung angefordert hat. Ich denke, ich brauche hier einen Pub / Sub-Mechanismus, in dem das Backend des Arbeiters veröffentlicht und die Web-App abonniert. Wenn die Web-App eine Nachricht empfängt, reagiert sie darauf, indem sie eine Statusaktualisierung an den Client sendet. Ich möchte, dass das Worker-Backend skalierbar und stark von der Web-Anwendung entkoppelt ist. Daher habe ich darüber nachgedacht, Redis oder ZeroMQ für diese Aufgabe zu verwenden. Was denken Sie? Ist meine ganze Vorgehensweise ein bisschen zu kompliziert?

  2. Welche Technologie sollte ich verwenden, um Informationen in den Browser zu übertragen? Nur aus Perfektionismus möchte ich Echtzeit-Updates haben. Ich möchte nicht mit einer hohen Frequenz abfragen. Ich möchte sofortigen Push an den Client, wenn das Worker-Backend eine Nachricht ausgibt :-). Außerdem benötige ich keine maximale Browserunterstützung. Dieses Projekt ist für mich mehr oder weniger ein Techdemo. Sollte ich für HTML5 Server-versendete Ereignisse / WebSockets gehen? Oder würdest du es anders empfehlen?

Vielen Dank für Ihre Empfehlungen im Voraus.

    
Jan-Philip Gehrcke 04.10.2012, 18:57
quelle

3 Antworten

3

Um Ihre Anwendung zu nutzen, wird Ihre Webanwendung eine Datenbank haben. Ich würde eine Tabelle in dieser Datenbank erstellen, die speziell für diese Jobs ist. Sie würden für jeden Job einen 'Status' haben.

Dies vereinfacht Ihr System, weil Sie einfach Ihre Anfrage zum Starten eines Jobs abschicken und an die Backend-Mitarbeiter übergeben können (zmq ist eine gute Lösung für diesen IMO). Da Sie Python für das Backend verwenden, ist es sehr einfach, Ihre Worker-Jobs entweder den aktuellen Arbeitsauftrag in der Datenbank zu aktualisieren oder einen anderen 'Updater' zu haben, dessen einzige Aufgabe darin besteht, Felder in der Datenbank zu aktualisieren wird für eine bessere Lösung sorgen, ermöglicht es Ihnen, möglicherweise mehrere 'Updater' zu starten, wenn Sie viele Aktualisierungen durchführen)

Dann würden Sie für Ihr Frontend, da Sie den Server nicht abfragen möchten, etwas von einer langen Umfrage machen. Was Sie im Wesentlichen tun, ist das Abrufen des Servers, aber der Server Nevers antwortet tatsächlich, bis sich die Daten, an denen Sie interessiert sind, geändert haben. Sobald es eine Änderung gibt, antworten Sie mit der Anfrage. Am Frontend lässt du deine JS die Verbindung wiederherstellen, sobald sie das neueste Update erhält. Diese Lösung ist browserübergreifend kompatibel, solange Sie ein JS-Framework verwenden, das auch browserübergreifend ist (ich würde jQuery vorschlagen).

Um das Abrufen der Web-Apps-Datenbank zu verhindern, gehen Sie wie folgt vor:

Machen Sie die erste Anfrage eine lange Umfrage Anfrage an die Web-App, sendet die Web-App eine zmq-Nachricht an Ihr Backend (wahrscheinlich würde mit einem REQ / REP-Socket getan werden müssen) und wartet. Es wartet, bis es eine Nachricht vom zmq-Backend mit einer Statusänderung erhält. Wenn es eine Statusänderung erhält, antwortet es dem Frontend mit der Änderung. An diesem Punkt sendet das Frontend eine neue Long-Poll-Anfrage (mit dieser aktuellen ID des Jobs, die seine Identität sein kann) und die Web-App wird sich wieder mit dem Backend verbinden und auf eine weitere Statusänderung warten. Der Trick, dies zu erreichen, ist die Verwendung von ZMQs ZMQ_IDENTITY für den Socket, als es ursprünglich war erstellt (in der ersten Anfrage). Dadurch kann sich die Webanwendung erneut mit demselben Back-End-Socket verbinden und neue Updates erhalten. Wenn das Backend ein neues Update zum Senden hat, wird es der Web-App signalisieren, die wiederum auf die lange Poll-Anfrage mit ihrer Statusänderung reagiert. Auf diese Weise gibt es keine polling , keine Backend-Datenbank und alles wird ereignisgesteuert von den Backend-Arbeitern ausgeführt.

Ich habe eine Art Überwachungshund eingerichtet, dass, wenn das Frontend weggeht (Seiten umschalten oder Browser schließen), die Backend-Sockets ordnungsgemäß geschlossen werden. Es ist nicht nötig, dass sie dort sitzen und unbestimmt blockieren, wenn sich ihr Zustand ändert.

    
g19fanatic 05.10.2012, 12:19
quelle
4

Eine Option wäre die Verwendung von WebSocket. Wenn Sie diesen Weg gehen, können Sie sich Autobahn , die Clients und Server für Python (Twisted) enthält, sowie ein RPC + PubSub-Protokoll ansehen über WebSocket (mit Bibliotheken für Python, JavaScript und Android). Die Verwendung eines RPC + PubSub-Abonnements spart erhebliche Arbeit und passt möglicherweise zu Ihren Anforderungen (Job-Vorlage = & gt; RPC, Job-Arbeitsupdates = & gt; PubSub).

AutobahnPython läuft auf Twisted, das zusätzlich als WSGI-Container fungieren kann, der Flask (oder ein anderes WSGI-basiertes Webframework) ermöglicht. Sie können alles auf 1 Port / Server ausführen. Es gibt ein Beispiel für das GitHub Autobahn-Repository für Letzteres.

Disclaimer: Ich bin Autor von Autobahn und WAMP und arbeite für Tavendo.

Details: Ich nehme an, dass Ihre Mitarbeiter CPU-intensive und / oder blockierende Sachen machen.

Erstens, sind Ihre Mitarbeiter reine Python oder externe Programme?

Wenn Letzteres gilt, können Sie Twisted-Prozessprotokollinstanzen verwenden, die über stdio-Pipes (auf nicht blockierende Weise) vom Twisted-Hauptthread kommunizieren. Wenn Sie Ersteres sind, können Sie den Twisted Hintergrund-Thread-Pool verwenden und Twisted deferToThread verwenden (siehe: Ссылка ) ).

Autobahn verläuft auf dem Haupt-Twisted-Reaktor-Gewinde. Wenn dies auch für Ihren Worker der Fall ist (siehe vorherige Kommentare), können Sie Methoden direkt in den WebSocket / WAMP-Factory- / Protokollinstanzen aufrufen. Wenn nicht (Worker wird im Hintergrundthread ausgeführt), sollten Sie diese Methoden über callFromThread aufrufen.

Wenn Sie WAMP verwenden, besteht die Hauptsache darin, für jeden Worker eine Referenz für die WampServerFactory zu erhalten. Der Worker kann dann ein PubSub-Ereignis an alle Abonnenten senden, indem er die entsprechende Factory-Methode aufruft.

    
oberstet 04.10.2012 20:59
quelle
3

Da Sie über eine Python-Webanwendung sprechen, würde ich Ihnen empfehlen, sich Folgendes anzusehen:

Welche Messaging-Technologie sollte ich zwischen Web-App und Worker-Backend anwenden?

Sellerie - Zerlegen Sie Ihre Aufträge in kleinere Aufgaben, die Ergebnisse liefern, die dem Kunden gezeigt werden müssen

Welche Technologie sollte ich verwenden, um Informationen an den Browser zu senden?

Entweder Socket IO auf der NodeJS Art der Serverseite JS-Framework oder eine Web-Socket-Bibliothek für Ihr Python-Web Rahmen

Wenn du nicht zu sehr mit Python verbunden bist, schau dir Meteor

an

Basierend auf diesem Thema , anderen Möglichkeiten, den Fortschritt vom Server zu aktualisieren Webclient in Echtzeit könnte den Fortschrittsstatus in eine Redis-Datenbank schreiben oder oribited / Morbid (beide basierend auf Verdreht ) mit STOMP-Protokoll basierend auf asynchronen Ergebnissen von Selleries Teilaufgaben

    
Pratik Mandrekar 04.10.2012 19:13
quelle