Datei cachen - ist dieses Verfahren technisch machbar?
Eddie
- webserver
Hallo allerseits,
ich moechte ein paar Grafiken, die eigentlich dynamisch erzeugt werden, auf der Festplatte "vorratsspeichern".
Der normale Ablauf wäre ja, soweit ich weiss, folgender:
das zuständige Skript (bspw. grafik.php) wird aufgerufen und schaut, ob die Grafik bereits existiert. Existiert sie, wird sie eben ausgeliefert. Existiert sie nicht, wird sie erzeugt, gespeichert und dann ausgeliefert.
Jetzt würde ich den Existenzcheck gerne zuerst machen!!! Also: die Grafik im Cache wird direkt verlinkt. Das würde meinen PHP-Parser entlasten, was mir nur Recht wäre!
Problem: was passiert, wenn die Grafik noch nicht existiert? Kann ich es so einrichten, dass der Server (Apache) die Anfrage erst dann auf mein Skript umleitet, und zwar so, dass der User und auch dessen Browser nichts davon mitkriegen?
Danke für eure Hilfe,
Eddie
Hi,
Der normale Ablauf wäre ja, soweit ich weiss, folgender:
das zuständige Skript (bspw. grafik.php) wird aufgerufen und schaut, ob die Grafik bereits existiert. Existiert sie, wird sie eben ausgeliefert. Existiert sie nicht, wird sie erzeugt, gespeichert und dann ausgeliefert.Jetzt würde ich den Existenzcheck gerne zuerst machen!!! Also: die Grafik im Cache wird direkt verlinkt. Das würde meinen PHP-Parser entlasten, was mir nur Recht wäre!
Richte Dein PHP-Script als error-Document für 404 not found für das Verzeichnis mit den Grafiken ein.
Sorg dann dafür, daß es nach erfolgreichem Erzeugen der Graphik diese mit passendem Status (200 ok) ausliefert.
cu,
Andreas
Hallo nochmal,
Richte Dein PHP-Script als error-Document für 404 not found für das Verzeichnis mit den Grafiken ein.
Sorg dann dafür, daß es nach erfolgreichem Erzeugen der Graphik diese mit passendem Status (200 ok) ausliefert.
Danke dir Andreas, das klingt doch schonmal garnicht so kompliziert, wie ich mir das gedacht habe :-)
Jetzt habe ich aber doch noch eine etwas allgemeinere Frage, weil ich mich gerade wundere, ob ich das Konzept des Cachings nicht etwas unterschaetze. Für mich klingt das bisher alles recht einfach:
Das klingt ja alles sehr einfach. Übersehe ich da was? Gibt es bspw. zusätzliche Mechanismen, die ich vorsehen sollte, falls richtig viele (>100.000) Dateien zusammenkommen?
Ihr seht, ich mach das grad zum ersten Mal :-)
Eddie
Hi,
Jetzt habe ich aber doch noch eine etwas allgemeinere Frage, weil ich mich gerade wundere, ob ich das Konzept des Cachings nicht etwas unterschaetze. Für mich klingt das bisher alles recht einfach:
- jede neue Grafik kommt ins Verzeichnis /cache/
- bei jedem Aufruf bekommt die entsprechende Datei ein neues Zugriffsdatum verpasst
- in regelmäßigen Abständen lasse ich einen Cronjob laufen, der dann abhängig vom Zugriffsdatum aufräumt
Ggf. das Löschen von alten Dateien nicht per Cronjob, sondern vom graphik-erzeugenden Script mit erledigen lassen:
Wenn das Script feststellt, daß mehr als n Graphiken existieren, lösche die ältesten.
cu,
Andreas
Hello,
Ggf. das Löschen von alten Dateien nicht per Cronjob, sondern vom graphik-erzeugenden Script mit erledigen lassen:
Wenn das Script feststellt, daß mehr als n Graphiken existieren, lösche die ältesten.
Das wird aber, wenn ich Edii richtig verstanden habe, vom User angestoßen. Und der müsste dann solange warten....................................................
Das ist nicht so günstig.
Harzliche Grüße vom Berg
http://www.annerschbarrich.de
Tom
Hi,
Ggf. das Löschen von alten Dateien nicht per Cronjob, sondern vom graphik-erzeugenden Script mit erledigen lassen:
Wenn das Script feststellt, daß mehr als n Graphiken existieren, lösche die ältesten.Das wird aber, wenn ich Edii richtig verstanden habe, vom User angestoßen. Und der müsste dann solange warten....................................................
1. kann man ja auch erst die neue Graphik erstellen und ausliefern und dann die Dateien löschen
2. sooo ewig dauert das Löschen von einer Handvoll Graphiken ja auch nicht (viel mehr können es ja eigentlich nicht werden, da ja bei Überschreiten der Anzahl gleich gelöscht wird).
cu,
Andreas
Hello,
Das wird aber, wenn ich Edii richtig verstanden habe, vom User angestoßen. Und der müsste dann solange warten....................................................
- kann man ja auch erst die neue Graphik erstellen und ausliefern und dann die Dateien löschen
Nö, denn das Script läuft dann trotzdem solange bis zum ConnectionClose() und der User muss warten.
- sooo ewig dauert das Löschen von einer Handvoll Graphiken ja auch nicht (viel mehr können es ja eigentlich nicht werden, da ja bei Überschreiten der Anzahl gleich gelöscht wird).
Man könnte das Löschscript aber abspalten oder am besten gelich einen Systembefehl benutzen mittels exec().
Harzliche Grüße vom Berg
http://www.annerschbarrich.de
Tom
hi,
- kann man ja auch erst die neue Graphik erstellen und ausliefern und dann die Dateien löschen
Nö, denn das Script läuft dann trotzdem solange bis zum ConnectionClose() und der User muss warten.
flush() existiert ja.
Und ob die Verbindung nach dem Empfangen des Bildes noch ein weniggehalten wird, weil das Script im Hintergrund noch etwas anderes macht, dürfte den User nicht sonderlich stören.
gruß,
wahsaga
Hello,
flush() existiert ja.
Und ob die Verbindung nach dem Empfangen des Bildes noch ein weniggehalten wird, weil das Script im Hintergrund noch etwas anderes macht, dürfte den User nicht sonderlich stören.
Das hängt vom Browser ab.
Er kann wahrscheinlich nichts anders machen, als zu warten, oder aber den Cancel-Button zu drücken.
Harzliche Grüße vom Berg
http://www.annerschbarrich.de
Tom
Hallo allerseits,
danke euch fuer eure rege Beteiligung, das hilft mir sehr!
Ich denke, in meinem Fall wird ein stuendlicher Cronjob genuegen, der im Hintergrund ablaeuft. Im Grunde werde ich zwei Sorten Dateien haben, naemlich "Testversionen" (die zustande kommen, wenn der User rumexperimentiert) und endgültige Versionen.
Die Testversionen werden eine kurze Haltbarkeit haben (bspw. eine Stunde oder sogar nur 5 Minuten), abhaengig von ihrem ERSTELLUNGSDATUM.
Die endgültigen Versionen haben dann eine laenger Haltbarkeit (bspw. 24 Stunden), aber abhaengig von ihrem LETZTEN ZUGRIFFSDATUM. Werden sie also regelmaessig verwendet, kann ihre Haltbarkeit durchaus der Projektlaufzeit entsprechen.
Eddie
Moin!
Das klingt ja alles sehr einfach. Übersehe ich da was? Gibt es bspw. zusätzliche Mechanismen, die ich vorsehen sollte, falls richtig viele (>100.000) Dateien zusammenkommen?
Wenn du sehr viele Dateien voraussiehst, solltest du die nicht alle in ein einziges Verzeichnis packen, sondern mehrere Verzeichnisse dafür vorsehen.
Typische Applikationen, die unbekannt viele Dateien erzeugen könnten, und deren Dateinamen z.B. Hexzahlen sind, erzeugen meist folgende Struktur:
Dateiname beginnt mit 0FE3....
Datei liegt in /prefix/0/F/E/3/0FE3....
Das kann man in vier Stufen machen, wie im Beispiel, oder auch in weniger oder mehr (sofern das Szenario wirklich von Millionen oder Milliarden Dateien ausgeht).
- Sven Rautenberg
Hallo Sven,
Typische Applikationen, die unbekannt viele Dateien erzeugen könnten, und deren Dateinamen z.B. Hexzahlen sind,
Genau so wird es sein! Der Dateiname ist im Grunde eine Argumentliste, der z.B. die Beschriftung des Bildes definiert. D.h. es kann schon vorkommen zwei Leute die selbe Datei mit demselben Namen brauchen.
Dateiname beginnt mit 0FE3....
Datei liegt in /prefix/0/F/E/3/0FE3....
Cool, so werde ich das machen!
Danke dir,
Eddie
Hi,
Ihr seht, ich mach das grad zum ersten Mal :-)
Denk dann auch dran, "Expires"- und "Last-Modified"-Header mitzuliefern und ggf. unnötige Requests mit einem "304"Header zu beantworten, ohne die Bilddaten unnötig durch die Leitung zu pusten ...
Gruß, Cybaer
Hallo Cybaer,
bin mir nicht sicher, ob ich das richtig verstanden habe:
Denk dann auch dran, "Expires"- und "Last-Modified"-Header mitzuliefern
Welchem Zweck dient das? "Expires" sollte eigentlich garnicht vorkommen, da die Dateien (egal, ob sie physikalisch existieren oder nicht) dauerhaft gueltig sein werden.
Und bei "Last-Modified" gilt eigentlich dasselbe: die Dateien koennen nicht verändert werden. Werden sie verändert, dann ändert sich auch der Dateiname (vgl. meine Antwort auf Sven's Beitrag).
Brauche ich diese Header-Angaben also trotzdem?
und ggf. unnötige Requests mit einem "304"Header zu beantworten, ohne die Bilddaten unnötig durch die Leitung zu pusten ...
Oh Gott, wusste ich ja garnicht, dass es sowas gibt, peinlich! Macht der Apache sowas automatisch? Oder muss ich ihn dazu anweisen?
Also, um mal abzuschweifen: http://www.umdiewelt.de hält zur Zeit ca. 45.000 Bilder parat, die mir monatlich 100GB Traffic bescheren. Wie kann ich feststellen, ob da bereits 304 genutzt wird?
Eddie
Hi,
Welchem Zweck dient das? "Expires" sollte eigentlich garnicht vorkommen, da die Dateien (egal, ob sie physikalisch existieren oder nicht) dauerhaft gueltig sein werden.
Umso wichtiger!
Googel mal nach Expires Cache-Control ...
Und bei "Last-Modified" gilt eigentlich dasselbe: die Dateien koennen nicht verändert werden. Werden sie verändert, dann ändert sich auch der Dateiname (vgl. meine Antwort auf Sven's Beitrag).
Umso wichtiger!
Brauche ich diese Header-Angaben also trotzdem?
Also wenn Du Traffic sparen (und dem User möglichst wenig Traffic zumuten) möchtest: Ja.
und ggf. unnötige Requests mit einem "304"Header zu beantworten, ohne die Bilddaten unnötig durch die Leitung zu pusten ...
Macht der Apache sowas automatisch? Oder muss ich ihn dazu anweisen?
Der Apache macht das automatisch - bei statischen Dateien. Du generierst den Output on-the-fly - also mußt Du dich auch selbst drum kümmern.
Wenn Du dem Client sagst, er soll sich bei einem wiederholten Aufruf aus seinem Cache bedienen, dann macht er das ggf. auch. Wenn Du ein Last-Modified- oder ETag-Header schickst, dann fragt sendet der Client beim erneuten Request diese Daten mit, Du kannst dann entscheiden, ob sich die Daten mittlerweile geändert haben, und statt 200 & Daten einen 304 ohne Daten schicken.
Wenn sich deine Daten aber ohnehin nie nicht ändern, dann kannst Du dir aber vielleicht die Überprüfung auch ersparen (unsauber, aber schnell implementiert ;-)): schick doch einfach ein willkürliches ETag mit, und wenn ein Request mit einer ETag-Nachfrage kommt, dann hat der Client die Daten schon ;->:
<?php
if(!empty($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH']=='never-changed') {
header('Status: 304 Not Modified');
header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified');
header('Connection: close');
die();
} else {
header('ETag: never-changed');
// Hier noch Expires- und Cache-Control-Header nach Wunsch
send_data();
}
?>
wobei send_data() die Funktion ist, die dann die Bilddaten ausliefert ...
Also, um mal abzuschweifen: http://www.umdiewelt.de hält zur Zeit ca. 45.000 Bilder parat, die mir monatlich 100GB Traffic bescheren. Wie kann ich feststellen, ob da bereits 304 genutzt wird?
Im Log steht jeweils der Statuscode des Requests. Z.B. 200 (erfolgreich) inkl. der übertragenen Bytes, oder eben 304, dann üblicherweise ohne Bytes (der Client hatte die Daten ja schon).
Gruß, Cybaer
Hallo Cybaer,
super, danke dir! Das hat mal sehr viel Klarheit geschaffen bei mir :-)
Der Apache macht das automatisch - bei statischen Dateien. Du generierst den Output on-the-fly - also mußt Du dich auch selbst drum kümmern.
Im Log steht jeweils der Statuscode des Requests. Z.B. 200 (erfolgreich) inkl. der übertragenen Bytes, oder eben 304, dann üblicherweise ohne Bytes (der Client hatte die Daten ja schon).
Ok, Entwarnung, ist genau, wie du sagst, ueberall 304er :-)
Eddie
Hi,
und ggf. unnötige Requests mit einem "304"Header zu beantworten, ohne die Bilddaten unnötig durch die Leitung zu pusten ...
Macht der Apache sowas automatisch? Oder muss ich ihn dazu anweisen?
Der Apache macht das automatisch - bei statischen Dateien. Du generierst den Output on-the-fly - also mußt Du dich auch selbst drum kümmern.
Also nach meinem Vorschlag wären die Dateien statisch - nur, falls eine Graphik nicht existiert, springt das Script ein, das die Datei dann erzeugt ...
cu,
Andreas
Hallo Andreas,
Also nach meinem Vorschlag wären die Dateien statisch - nur, falls eine Graphik nicht existiert, springt das Script ein, das die Datei dann erzeugt ...
Genau! Und in diesem Fall kann ich's ja mit Cybaers Vorschlag kombinieren.
Eddie