Ich hab mal eine allgeimeine Frage, wie ich den Server etwas im hintergrund "berechnen" lasse ohne den User etwas davon "spüren" zu lassen?! geht das überhaupt?
konkretes Beispiel:
- User läd eine Datei hoch mit 100.000.000 Mathe Aufgaben (Multiplikation, ich weiß...dauert nicht lange aber gehen wir davon aus, dass der Server 1 Minute benötigen würde, um das Ergebnis zu liefern)
- es erscheint eine Meldung datei erfolgreich hochgeladen...
- User benutzt die Internetseite weiter (durchstöbern, evtl. nächste datei hochladen)
- User geht 5 Minuten später wieder an seinen Account und zack steht das Ergebnis als Nachricht für ihn bereit
ginge so etwas? sprich der User führt seine Aktivitäten weiter aus und im hintergrund wird etwas ausgeführt/berechnet? Wie würde man so etwas realisieren? also dem Server mitteilen mache etwas gleichzeitig oder im Hintegrund?
Danke
liebe Grüße
Dan
Den Server rechnen lassen (allgemeine Frage) zu Bottle
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Würde gehen, wenn du die zwei Aufgaben auseinander koppelst: Also Webseite und das eigentliche "berechnen"...
Brauchst halt einen im Hintergrund laufenden Deamon der unabhängig von dem Webserver die neuen Aufgaben abarbeitet.
Dem Rechner-Job könnte man dann noch die entsprechende CPU-Priorität zuweisen, damit der den Webserver nicht ausbremst...
Brauchst halt einen im Hintergrund laufenden Deamon der unabhängig von dem Webserver die neuen Aufgaben abarbeitet.
Dem Rechner-Job könnte man dann noch die entsprechende CPU-Priorität zuweisen, damit der den Webserver nicht ausbremst...
ahja und was für ein "daemon" wäre das? (google spuckt daemon-tools aus und das ist nicht ganz das was ich brauche
) tut mir leid wenn ich so dumm frage aber ich kenn mich damit überhaupt nicht aus...
was genau meinst du mit auseinander koppeln ?
Die Daten zum Webserver hochladen und dann dem "daemon" sagen "rechne!" ?
ein paar links oder tuts oder so wären hilfreich
Danke

was genau meinst du mit auseinander koppeln ?
Die Daten zum Webserver hochladen und dann dem "daemon" sagen "rechne!" ?
ein paar links oder tuts oder so wären hilfreich

Danke
@DanJJo: Das wäre ein Daemon den *Du* schreiben müsstest. Eben ein dauerhaft laufender Prozess der für das berechnen zuständig ist. *Diese* daemontools könnten da tatsächlich nützlich sein, wobei ich supervisord bevorzuge.
Mit entkoppeln ist gemeint, dass der Rechnen-Prozess unabhängig von Deiner Webanwendug läuft. Hier kommt es übrigens wieder stark auf den Webspace-Anbieter an, ob der lang laufende Prozesse erlaubt. Viele billige Anbieter erlauben das nicht und killen Benutzerprozesse nach einer gewissen Laufzeit einfach.
Mit entkoppeln ist gemeint, dass der Rechnen-Prozess unabhängig von Deiner Webanwendug läuft. Hier kommt es übrigens wieder stark auf den Webspace-Anbieter an, ob der lang laufende Prozesse erlaubt. Viele billige Anbieter erlauben das nicht und killen Benutzerprozesse nach einer gewissen Laufzeit einfach.
also sowas in der Art beim Website aufruf starten?! natürlich gestartet bei fileupload und schlafengelegt bis fileupload
EDIT*: Könnte ich denn supervisord auf einem Server installieren und dort einfach starten ?
Code: Alles auswählen
import daemon
import time
def do_something():
while True:
with open("/tmp/current_time.txt", "w") as f:
f.write("The time is now " + time.ctime())
time.sleep(5)
def run():
with daemon.DaemonContext():
do_something()
@DanJJo: Nicht beim Webseitenaufruf starten sondern generell parallel zum Webserver ausführen. Halt einen Server der Berechnungen durchführt.
Natürlich kannst Du ``supervisord`` auf einem Server installieren. Natürlich nur wenn Du das darfst, also die nötigen Rechte dazu hast und wenn Du langlaufende Prozesse haben kannst. Falls es zufällig um Uberspace als Hoster geht, die haben Unterstützung für ``daemontools``: Uberspace.de — daemontools.
Natürlich kannst Du ``supervisord`` auf einem Server installieren. Natürlich nur wenn Du das darfst, also die nötigen Rechte dazu hast und wenn Du langlaufende Prozesse haben kannst. Falls es zufällig um Uberspace als Hoster geht, die haben Unterstützung für ``daemontools``: Uberspace.de — daemontools.
Also ich hab mich ein wenig mit diesen daeomonen befasst und ich weiß nicht, ob ich es richtig mache...
Ich hab daemontools installiert und ind die /etc/init/svscan.conf folgendes geschrieben.
weitere verstehe ich nun nicht wie das mit den "Service" Ordner abläuft. Erstelle ich einen neuen mkdir -p /etc/service/testdaemon Ordner und gebe diesem chmod 1755 und lege dort meine test_daemon.py ab ? und starte dann diese mit exec setuidgid testdaeomon /usr/bin/python test_daemon.py ? also bei mir verschwindet dann nur das Terminal und nichts passiert also mach ich bestimmt irgendetwas falsch, da in die current_time.txt nichts geschrieben wird.
Danke
sonnigen Sonntag noch!
Grüße
Dan
die test_daemon.py nochmal...
EDIT*:
also ich hab mein "daemon" zum laufen bekommen mit dieser Anleitung http://thedjbway.b0llix.net/daemontools/blabbyd.html. Mit svstat /service/test_daemon sehe ich auch das mein daemon läuft aber er speichert nichts in curren_time.txt...
meine run ruft die python datei mit exec python test_daemon.py auf. Erkennt einer meinen Fehler ?
Ich hab daemontools installiert und ind die /etc/init/svscan.conf folgendes geschrieben.
Code: Alles auswählen
start on runlevel [12345]
stop on runlevel [^12345]
respawn
exec /command/svscanboot
Danke

sonnigen Sonntag noch!
Grüße
Dan
die test_daemon.py nochmal...
Code: Alles auswählen
import daemon
import time
def do_something():
while True:
with open("/tmp/current_time.txt", "w") as f:
f.write("The time is now " + time.ctime())
time.sleep(5)
def run():
with daemon.DaemonContext():
do_something()
also ich hab mein "daemon" zum laufen bekommen mit dieser Anleitung http://thedjbway.b0llix.net/daemontools/blabbyd.html. Mit svstat /service/test_daemon sehe ich auch das mein daemon läuft aber er speichert nichts in curren_time.txt...
meine run ruft die python datei mit exec python test_daemon.py auf. Erkennt einer meinen Fehler ?
@DanJJo: Als erstes solltest Du prüfen ob beide „Enden” die Du verbinden möchtest für sich genommen funktionieren. Also auf der einen Seite ob die daemontools laufen, also ob tatsächlich ein `svscan`-Prozess läuft, der ein Service-Verzeichnis überwacht.
Eine ``/etc/init/svscan.conf`` anlegen hat erst einmal keinen Effekt bis man entweder den Rechner neu startet, oder (ich gehe mal von `upstart` aus) mit ``initctl start svscan`` mit den entsprechenden Rechten diesen Dienst startet.
An der Stelle wundere ich mich nämlich über das ``/command/``. Falls das nicht eine besonderheit vom Init-System ist — da kenne ich mich jetzt nicht so gut aus — dann gibt es diesen Pfad nicht und ``svscanboot`` kann so nicht gestartet werden. Ich habe an der Stelle ``exec /usr/bin/svscanboot`` stehen, was auch dem kompletten Pfad zu ``svscanboot`` auf meinem System entspricht.
Am anderen „Ende” hast Du Deinen Testdaemon. Der läuft natürlich nicht, denn es werden nur zwei Funktionen definiert und das war es dann auch schon. Das hätte man ziemlich schnell bemerkt, wenn man den einfach mal von Hand gestartet hätte. Da fehlt also so etwas wie
damit sich überhaupt etwas tut.
Wo Du das Programm ablegst ist nahezu egal. In dem Verzeichnis für den Service muss ein Skript mit dem Namen ``run`` liegen welches das Programm *im Vordergrund* startet.
Das bedeutet das `daemon`-Modul brauchst Du überhaupt nicht, im Gegenteil das darfst Du so gar nicht verwenden weil es den Prozess in den Hintergrund befördert. Aus der daemontools-FAQ:
Das ``supervise/``-Unterverzeichnis legen die daemontools an, da sind Verwaltungsdaten und Statusinformationen gespeichert.
Solange man einen Dienst nicht mit ``svc -d`` stoppt, und der Dienst nicht schon läuft, versuchen die daemontools regelmässig das ``run``-Skript auszuführen. Wenn man an dem etwas ändern möchte sollte man das nicht direkt tun, sondern an einer Kopie und die dann am Ende in ``run`` umbenennen, damit es nicht passieren kann, dass die daemontools eine ``run`` ausführen an der man gerade arbeitet.
Eine ``/etc/init/svscan.conf`` anlegen hat erst einmal keinen Effekt bis man entweder den Rechner neu startet, oder (ich gehe mal von `upstart` aus) mit ``initctl start svscan`` mit den entsprechenden Rechten diesen Dienst startet.
An der Stelle wundere ich mich nämlich über das ``/command/``. Falls das nicht eine besonderheit vom Init-System ist — da kenne ich mich jetzt nicht so gut aus — dann gibt es diesen Pfad nicht und ``svscanboot`` kann so nicht gestartet werden. Ich habe an der Stelle ``exec /usr/bin/svscanboot`` stehen, was auch dem kompletten Pfad zu ``svscanboot`` auf meinem System entspricht.
Am anderen „Ende” hast Du Deinen Testdaemon. Der läuft natürlich nicht, denn es werden nur zwei Funktionen definiert und das war es dann auch schon. Das hätte man ziemlich schnell bemerkt, wenn man den einfach mal von Hand gestartet hätte. Da fehlt also so etwas wie
Code: Alles auswählen
if __name__ == '__main__':
run()
Wo Du das Programm ablegst ist nahezu egal. In dem Verzeichnis für den Service muss ein Skript mit dem Namen ``run`` liegen welches das Programm *im Vordergrund* startet.
Das bedeutet das `daemon`-Modul brauchst Du überhaupt nicht, im Gegenteil das darfst Du so gar nicht verwenden weil es den Prozess in den Hintergrund befördert. Aus der daemontools-FAQ:
Minimales Beispiel:http://cr.yp.to/daemontools/faq/create.html#run hat geschrieben: How do I create a service directory?
Answer: The only required component of your service directory is an executable file, ./run, that runs your daemon in the foreground, exiting when your daemon exits.
Code: Alles auswählen
bj@god:~$ ls /etc/service/testdaemon
run supervise testdaemon.py
bj@god:~$ cat /etc/service/testdaemon/run
#!/bin/bash
exec ./testdaemon.py
bj@god:~$ cat /etc/service/testdaemon/testdaemon.py
#!/usr/bin/env python
import time
def do_something():
while True:
with open('/tmp/current_time.txt', 'w') as time_file:
time_file.write('The time is now {0}\n'.format(time.ctime()))
time.sleep(5)
if __name__ == '__main__':
do_something()
bj@god:~$ sudo svc -u /etc/service/testdaemon/
bj@god:~$ sudo svstat /etc/service/testdaemon
/etc/service/testdaemon: up (pid 16611) 3 seconds
bj@god:~$ sudo svstat /etc/service/testdaemon
/etc/service/testdaemon: up (pid 16611) 6 seconds
bj@god:~$ cat /tmp/current_time.txt
The time is now Sun Aug 4 12:55:50 2013
Solange man einen Dienst nicht mit ``svc -d`` stoppt, und der Dienst nicht schon läuft, versuchen die daemontools regelmässig das ``run``-Skript auszuführen. Wenn man an dem etwas ändern möchte sollte man das nicht direkt tun, sondern an einer Kopie und die dann am Ende in ``run`` umbenennen, damit es nicht passieren kann, dass die daemontools eine ``run`` ausführen an der man gerade arbeitet.



EDIT*:
also ich hab mal Angefangen und viele Fragen kommen auf.
Sagen wir ich hab eine def aus einer main.tpl die so aussieht:
Code: Alles auswählen
import daemon_folder.test_daemon as daemon
install(SQLitePlugin(dbfile="test.db"))
...
@route("/berechne_lang/", method='POST')
def berechne_lang(db):
# get data from template
data = request.forms.getall('datas')
daemon(data[0],data[1])
return template("hauptmenu")
Code: Alles auswählen
#!/usr/bin/env python
install(SQLitePlugin(dbfile="test.db"))
def do_something(x,y):
erg = x + y
row = db.execute('INSERT INTO erg (erg) values (?)',(erg,))
if __name__ == '__main__':
do_something(x,y)
So würde es funktionieren aber es scheint mir nicht wirklich "elegant" und "effizient" zudem wird mein Rechner spürbar langsamer und wärmer
das ist jetzt noch ein bsp ohne db und templates etc um heraus zu finden "how to make it happen" :K
Ich schreibe was ich möchte in eine file und lasse den Daemon diese Auslesen....
daemon.py
berechne.py
es muss doch eine besser lösung geben oder?!

das ist jetzt noch ein bsp ohne db und templates etc um heraus zu finden "how to make it happen" :K
Ich schreibe was ich möchte in eine file und lasse den Daemon diese Auslesen....
daemon.py
Code: Alles auswählen
#!/usr/bin/env python
import os
def summe():
while True:
if os.path.getsize('/tmp/worker.txt') > 0:
with open('/tmp/worker.txt', 'r') as infile:
values = infile.read().split('#')
erg = int(values[0])+int(values[1])
with open('/tmp/rslt.txt', 'w') as wrslt:
wrslt.write("Erg ist {0}".format(erg))
open('/tmp/worker.txt', 'a').close()
else:
pass
if __name__ == '__main__':
summe()
Code: Alles auswählen
def berechne_lang(x,y):
with open('/tmp/worker.txt', 'w') as outfile:
outfile.write("{0}#{1}".format(x,y))
return "fertig_berechne_lang"
@DanJJo: Dein Prozess verbrät nicht nur seine eigene Rechenzeit, sondern beschäftigt auch noch den Kernel andauernd.
Wenn Du tatsächlich auf Dateisystembasis arbeiten willst, gibt es inotify oder ähnliches um Änderungen in Verzeichnissen resourcenschonend abzufragen. Alternativ sei auf alle möglichen Arten der Interprocesskommunikation hingewiesen (Pipes, Sockets, ...)
Wenn Du tatsächlich auf Dateisystembasis arbeiten willst, gibt es inotify oder ähnliches um Änderungen in Verzeichnissen resourcenschonend abzufragen. Alternativ sei auf alle möglichen Arten der Interprocesskommunikation hingewiesen (Pipes, Sockets, ...)
Sirius3 hat geschrieben:@DanJJo: Dein Prozess verbrät nicht nur seine eigene Rechenzeit, sondern beschäftigt auch noch den Kernel andauernd.
Wenn Du tatsächlich auf Dateisystembasis arbeiten willst, gibt es inotify oder ähnliches um Änderungen in Verzeichnissen resourcenschonend abzufragen. Alternativ sei auf alle möglichen Arten der Interprocesskommunikation hingewiesen (Pipes, Sockets, ...)
die Frage ist: Muss ich überhaupt auf Dateisystembasis arbeiten ?! oder gibt es eine andere Möglichkeit dem Daemon Werte zu übergeben? EDIT* bevor eine Antwort kommt ich probiers mal mit einer Pipe
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Dann Pollt man aber die Datenbank, das ist auch nicht viel besser.jens hat geschrieben:Die abzuarbeitenden Daten in eine Datenbank schreiben, die gleichzeitig vom Deamon gelesen werden?
Ich frag mich eigentlich warum noch niemand Celery erwähnt hat, das wäre genau das worin man Hintergrundberechnungen aus ner Webapp verlagern kann.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
nein das passiert nicht. Vorgehen sollte so aussehen App und Daemon benutzen DB...Daemon berechnet etwas und speichert das in die DB. Es soll sich nichts in die Quere kommen. Wäre zumindest Optimal.jens hat geschrieben:Die abzuarbeitenden Daten in eine Datenbank schreiben, die gleichzeitig vom Deamon gelesen werden?
ich habs mal mit einer pipe probiert aber auch die lässt den Rechner ordentlich heiss werden was auch nicht so gut ist :\
daemon.py
Code: Alles auswählen
#!/usr/bin/env python
from multiprocessing import Process, Pipe
import sys
def do_something():
while True:
try:
for val in values:
values = sys.stdin.readline()
erg = values[0]+values[1]
row = db.execute('INSERT INTO erg (erg) values (?)',(erg,))
except EOFError:
pass
if __name__ == '__main__':
do_something()
Code: Alles auswählen
import subprocess
def berechne_lang(values):
p = subprocess.Popen(['python', 'daemon.py'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
for val in values
p.stdin.write(str(val))
p.stdin.flush()
return "egal_was"
@Leonidas: Na weil das wahrscheinlich wieder einen ganzen Haufen Folgefragen nach sich zieht wie man das auf Uberspace installiert/nutzt. 

@DanJJo: Mit der Pipe musst Du Doch aber den Daemon von dem Prozess aus starten der die Daten bereit stellt. Dann könntest Du das auch gleich in dem selben Prozess berechnen lassen. Wenn Du mit einem separaten Daemon-Prozess kommunizieren willst, dann doch eher über „named pipes”. Da es dort aber zu Problemen kommen kann wenn mehrere Prozesse gleichzeitig Daten loswerden wollen, ist eine Kommunikation über Sockets vielleicht besser geeignet. Da kannst Du einen eigenen Thread für die Berechnungen machen und gegebenenfalls auch einen Thread pro Client, der die Daten entgegen nimmt und in eine Queue zum bearbeiten ablegt.
BlackJack hat geschrieben:@DanJJo: Mit der Pipe musst Du Doch aber den Daemon von dem Prozess aus starten der die Daten bereit stellt. Dann könntest Du das auch gleich in dem selben Prozess berechnen lassen. Wenn Du mit einem separaten Daemon-Prozess kommunizieren willst, dann doch eher über „named pipes”. Da es dort aber zu Problemen kommen kann wenn mehrere Prozesse gleichzeitig Daten loswerden wollen, ist eine Kommunikation über Sockets vielleicht besser geeignet. Da kannst Du einen eigenen Thread für die Berechnungen machen und gegebenenfalls auch einen Thread pro Client, der die Daten entgegen nimmt und in eine Queue zum bearbeiten ablegt.
Ohje...irgendwie hab ich mir das alles etwas einfacher vorgstellt

