Asynchrone Dateispeicherung von Benutzeruploads

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
metty
User
Beiträge: 99
Registriert: Samstag 13. Dezember 2008, 19:30

Hallo zusammen,

ich bastle derzeit an einer Speicherlösung für Dateien, die ein User auf einer Website hochgeladen hat. Für die endgültige Speicherung möchte ich GridFS, statt des normalen Dateisystems verwenden. Wurde die Datei erfolgreich im GridFS gespeichert, wird eine ID zurückgeliefert, die ich für die Identifikation der Datei verwende.

Funktionieren tut das wie folgt:

Code: Alles auswählen

[Upload] => [tmp-Verzeichnis] => [GridFS]
Der Benutzer lädt die Datei hoch, diese wird wie üblich ins tmp-Verzeichnis gespeichert, anschließend wird die Datei im selben Request-Aufruf ins GridFS gespeichert.

Mein Problem bei der Sache dabei ist jetzt folgende:
Synchron (wie oben beschrieben) funktioniert das alles ganz gut, jedoch auf einem Testsystem ohne Last. Würden jetzt mehrere Benutzer parallel Dateien hochladen, könnte es zu Geschwindigkeitsproblem bzw. Verzögerungen kommen, die Dateien vom tmp-Verzeichnis ins GridFS zu bekommen. Das heißt der Benutzer muss solange warten, bis die Datei endgültig im GridFS angekommen ist, erst dann wird die Erfolgsmeldung zurückgegeben. Problem ist, der Benutzer muss warten und glaubt vielleicht das irgendetwas nicht ordentlich funktioniert hat und startet evtl. den Upload nochmal.

Jetzt meine Frage, wie könnte ich das Speichern der Datei ins GridFS soweit entkoppeln, das der Benutzer gleich nach dem Upload (ins tmp-Verzeichnis) eine Erfolgsmeldung bekommt und der Speicherungsprozess ins GridFS im Hintergrund weiter läuft. Eine Lösung mit einem Thread der gestartet wird um die Datei ins GridFS zu laden erscheint mir auch nicht als die beste Möglichkeit. Auch eine Entkopplung mit einem Messagequeue ist meines Erachtens nicht sinnvoll möglich. Eine AJAX-Lösung, wo alles beim User im Browser abläuft gefällt mir auch nicht sonderlich, weil man nicht garantieren kann, das alles 100%ig funktioniert.

Wie lösen das große Seiten wie scribd.com, tumblr.com oder facebook usw. wo viele Benutzer gleichzeitig Dateien hochladen? Einfach nur performante Storagesysteme, die ins System eingemountet sind? Facebook hat das jedenfalls anfangs so gemacht. Habt ihr eine Idee dazu das ganze zu entkoppeln?

Danke euch....
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Ich würde es über Jobs bzw. Worker-Threads regeln: Der Benutzer bekommt die Erfolgsmeldung und eine vorläufige ID, sobald die Datei im temp ist. In einem (oder mehreren) separaten Threads tut eine Schleife nichts anderes, als nacheinander Datein vom tmp ins GridFS zu verschieben. Sobald das passiert ist, wird die echte ID mit der vorläufigen verknüpft.

Du startest also nicht einen Thread für jeden Upload, sondern nur eine kleine Zahl Threads für alle Uploads. Damit stellst du auch sicher, das dein GridFS nicht überlastet wird, nur weil sich die Uploads für eine kurze Zeit häufen. Dein /tmp funktioniert als Puffer.
Bottle: Micro Web Framework + Development Blog
metty
User
Beiträge: 99
Registriert: Samstag 13. Dezember 2008, 19:30

Defnull hat geschrieben:Ich würde es über Jobs bzw. Worker-Threads regeln: Der Benutzer bekommt die Erfolgsmeldung und eine vorläufige ID, sobald die Datei im temp ist. In einem (oder mehreren) separaten Threads tut eine Schleife nichts anderes, als nacheinander Datein vom tmp ins GridFS zu verschieben. Sobald das passiert ist, wird die echte ID mit der vorläufigen verknüpft.
Hey...
Ich werde es so ähnlich machen. Wenn der Benutzer eine Datei hochgeladen hat und diese im Temp angekommen ist, erhält er brav seine Erfolgsmeldung und sämtliche Informationen zur Datei, Benutzer etc. wird in einen Message-Queue geschrieben (sowas wie Beanstalk), im Hintergrund kann dann ein Worker die Datei ins GridFS wursteln und die zurückgelieferte ID in die Datenbank schreiben.

Danke dir für den Denkanstoß...
Zuletzt geändert von metty am Montag 9. August 2010, 10:56, insgesamt 1-mal geändert.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Eventuell macht es auch Sinn einen Messaging Server wie RabbitMQ laufen zu lassen der als Queue fungiert und eine seperate Anwendung übernimmt dann solche Aufgaben. Das wäre erstmal schneller weil Threads in Python nicht wirklich parallel sind und ist auch deutlich einfacher fehlerfrei umzusetzen.
metty
User
Beiträge: 99
Registriert: Samstag 13. Dezember 2008, 19:30

DasIch hat geschrieben:Eventuell macht es auch Sinn einen Messaging Server wie RabbitMQ laufen zu lassen der als Queue fungiert und eine seperate Anwendung übernimmt dann solche Aufgaben. Das wäre erstmal schneller weil Threads in Python nicht wirklich parallel sind und ist auch deutlich einfacher fehlerfrei umzusetzen.
Keine Angst, ich löse das auch nicht mit Threads :wink:
Antworten