2011-01-12 10 views
5

Hallo
Ich werde eine Rails-Website einrichten, wo nach einigen anfänglichen Benutzereingaben einige schwere Berechnungen durchgeführt werden (via c-extension zu Ruby, wird Multithreading verwenden). Da diese Berechnungen fast die gesamte CPU-Zeit verbrauchen (auch Speicher), sollte nie mehr als eine Berechnung gleichzeitig ausgeführt werden. Außerdem kann ich keine (asynchronen) Hintergrundjobs (wie bei einem verzögerten Job) verwenden, da rails die Ergebnisse dieser Berechnung anzeigen muss und die Site ohne JavaScript funktionieren sollte.
also brauche ich einen separaten Prozess, wo alle Rails-Instanzen ihre Berechnungsanforderungen einreihen und auf die Antwort warten müssen (vielleicht eine Fehlermeldung, wenn die Warteschlange voll ist), eine Art synchroner Job-Manager.Ruby/Rails Synchron Job Manager

weiß jemand, ob es ein Juwel/Plugin mit solcher Funktionalität gibt? (nanite schien mir ziemlich cool, aber scheint nur asynchron zu sein, so die Schienen Instanzen würde nicht wissen, wenn die Berechnung abgeschlossen ist. Ist das korrekt?)
eine andere Idee ist, meine eigenen mit verteilten Ruby (DRB) zu schreiben, aber warum erfinde das Rad wieder, wenn es schon existiert?

jede Hilfe wäre willkommen!

EDIT: wegen Spitzen zaius ich glaube, ich der Lage sein, dies asynchron zu tun, also werde ich resque versuchen.

Antwort

5

Ruby hat mutexes/Semaphore.

können Sie eine Semaphore verwenden Sie nur eine ressourcenintensive Prozess zur gleichen Zeit geschieht zu machen.

jedoch die Idee, ein Front-End-Prozess blockiert, während andere Aufgaben scheinen beenden mir nicht richtig.Wenn ich das täte, würde ich einen Hintergrund-Worker verwenden und dann eine Seite (oder einen iframe) mit dem Aktualisierungs-Meta-Tag verwenden, um den Fortschritt kontinuierlich zu überprüfen.

Auf diese Weise können Sie den gleichen Code für beide aktiviert Javascript verwenden und behinderte Kunden. Und Ihre Web-App-Threads blockieren nicht.

+0

, dass metarefresh Sache möglich wäre, aber den Benutzer manuell die Seite neu zu laden, wenn die Berechnung nach der Aktualisierung nicht fertig ist, ist nicht in meinen Augen zu benutzerfreundlich. atm ich erwarte nicht zu viele Anfragen zur gleichen Zeit, also ist das Blockieren der Web-Threads kein großes Problem. aber du hast Recht, das ist kein schöner Weg, es zu tun. – user573335

+0

Sie können die Metaaktualisierung so oft durchführen, wie Sie möchten - wenn der Job nach der ersten Aktualisierung nicht beendet ist, zeigt er dieselbe Aktualisierungsseite und zeigt nur die letzte Seite an, sobald der Job erledigt ist. – zaius

+0

Nun, ich bin ein bisschen zögerlich, aber je mehr ich darüber nachdenke, desto besser scheint es, die Lösung asynchron zu sein, zumindest auf lange Sicht. Gibt es Job-Queues, die ich nach der erwarteten Task-Dauer fragen kann (aus einem Web-Thread) und die eine Fehlermeldung an den Web-Thread zurückgeben kann, wenn zu viele Jobs in der Warteschlange stehen? – user573335

1

Wenn Sie einen separaten Prozess haben, dann haben Sie einen Hintergrund-Job ... also entweder man kann es oder man kann nicht ...

Was habe ich getan ist die Website, um die Anfrage params schreiben zu einer Datenbank. Dann sucht ein separater Prozess in der Datenbank nach ausstehenden Anforderungen - unter Verwendung des Gem. daemons. Es erledigt die Arbeit und schreibt die Ergebnisse zurück in die Datenbank.

Die Website fragt die Datenbank ab, bis die Ergebnisse fertig sind, und zeigt sie an.

Obwohl ich Javascript verwenden, um es die Abfrage zu machen.

Wenn Sie Javascript wirklich nicht verwenden können, dann scheint es, dass Sie entweder die Arbeit im Web-Anforderungs-Thread erledigen müssen oder den Thread warten lassen müssen, bis der Hintergrund-Thread beendet ist.

Um den Web-Request-Thread warten zu lassen, führen Sie einfach eine Schleife aus und überprüfen Sie die Datenbank, bis die Antwort wieder gespeichert wird. Sobald es da ist, können Sie den Thread vervollständigen.

HTH, chris

+0

ok, wissen Sie, wie ich den Web-Request-Thread warten lassen kann, bis der Hintergrundjob fertig ist? Da der Web-Reutesthread den Hintergrundthread nicht erzeugen kann, weiß ich nicht, wie das geht. – user573335