fastix®: Fehlersuche in "PHP: Einfaches Caching für Webprojekte"

Moin!

Falls jemand Lust haben sollte, mal über

"PHP: Einfaches Caching für Webprojekte" zu schauen und vielleicht den einen oder anderen Fehler (oder gar eine Sicherheitslücke) zu finden - es wäre nett wenn ich die Chance bekäme, da was zu verbessern.

MFFG (Mit freundlich- friedfertigem Grinsen)

@dedlefix: Das Problem mit dem SIP-Server ist gelöst. Ich habe eine 10-Euro-Fritz-Box "debrandet", ein aktuelles Betriebssystem von AVM drauf gespielt und die tut, was sie soll. (und spart Strom, wenn ich das Dyndns-Problem auch noch löse.)

fastix

  1. Moin,

    es wäre nett wenn ich die Chance bekäme, da was zu verbessern.

    Jow, schreib mal bitte, was das SCript genau macht, ich verstehe nichts von PHP.

    Hotti

    PS: Was ist mit Last-Modified bei Dir? Das käschd der Browser ;)

    1. Moin!

      Jow, schreib mal bitte, was das SCript genau macht, ich verstehe nichts von PHP.

      Nun ja. Es baut aus der URL (ok, ohne Protokoll, Port und Server) und den Daten in POST, SESSION, COOKIE mit MD5 einen als Dateinamen brauchbaren String zusammen und prüft ob die Datei mit diesem Name im Cache existiert und jung genug ist.

      Wenn es so ist wird geschaut ob der User-Agent (Browser) Gepacktes mag und die passende Variante der Seite ausgeliefert.

      Wenn nicht wird das übrige PHP-Skript ausgeführt, alle Ausgaben werden aber abgefangen statt diese zu senden. Ist das eigentliche Skript beendet werden diese Daten gezippt und in das Cachefile geschrieben - stehen beim nächsten Aufruf zur Verfügung. Außerdem wird mal über den gesamten Cache geschaut, ob es da was zum Wegwerfen gibt.

      PS: Was ist mit Last-Modified bei Dir? Das käschd der Browser ;)

      Hilft aber nur bei einem Benutzer... oder jenen, die hinter einem Proxy hocken.

      MFFG (Mit freundlich- friedfertigem Grinsen)

      fastix

      1. Moin,

        Jow, schreib mal bitte, was das SCript genau macht, ich verstehe nichts von PHP.

        Nun ja. Es baut aus der URL (ok, ohne Protokoll, Port und Server) und den Daten in POST, SESSION, COOKIE mit MD5 einen als Dateinamen brauchbaren String zusammen und prüft ob die Datei mit diesem Name im Cache existiert und jung genug ist.

        Ok, verstehe, danke.

        PS: Was ist mit Last-Modified bei Dir? Das käschd der Browser ;)

        Hilft aber nur bei einem Benutzer... oder jenen, die hinter einem Proxy hocken.

        Sags malso: Es hilft jedem UserAgent, der Last-Mod. unterstützt und das sind auch die Bots, u.a. UAs mit oder ohne Proxy.

        Grüße aus Oppenheim am Rhein,
        Hotti

        1. Moin!

          Sags malso: Es hilft jedem UserAgent, der Last-Mod. unterstützt und das sind auch die Bots, u.a. UAs mit oder ohne Proxy.

          Ich habe davon gehört :)

          Mir geht es mehr um sowas:

          http://fastix.org/news.php hat ein etwas anderes Caching, das erfolgt pro Feed. Die vorherige nervtötende Warterei hat mich überhaupt auf die Idee gebracht.

          http://fastix.org/ - wird auch gecached. Grund: Die Seiten sind quasistatisch. Der Cache wird gelöscht wenn etwas geändert wird, beim nächsten Abruf wieder erzeugt. Statt nach 0,3 Sekunden ist die Seite nach 0,1 Sekunden ausgeliefert.

          In irgendeinem gut besuchten Forum erscheint ...
          http://www.fastix.org/netztools/?addr=forum.de.selfhtml.org&action=traceroute ... und hunderte klicken drauf. Mit Cache kommt zwar nicht die aktuelle Auskunft, aber die wie es vor ein paar Minuten war. Serverlast gespart, die Anzahl der Verbindungen bleibt niedrig und die durch das Abrufe verursachten Pings halten sich in Grenzen, wachsen nicht zu einer Flut an, was ja auch Folgen haben kann.

          MFFG (Mit freundlich- friedfertigem Grinsen)

          fastix

          1. moin,

            http://fastix.org/ - wird auch gecached. Grund: Die Seiten sind quasistatisch. Der Cache wird gelöscht wenn etwas geändert wird, beim nächsten Abruf wieder erzeugt. Statt nach 0,3 Sekunden ist die Seite nach 0,1 Sekunden ausgeliefert.

            Ha, endlich maln Foto von Dir ;)

            Und auch kein Last-Mod.

            Ja, es gibt mehrere Möglichkeiten, das Ausliefern einer Seite zu beschleunigen. Last-Mod. (LM) im einfachsten Fall: Das Script schickt einfach nur den LM-Header zum Webserver, der Webserver macht den Vergleich und entscheidet ob 200 oder 304. Nachteil: Das Script läuft stets bis zum Ende durch.

            LM etwas verbessert: Das Script macht selbst den Vergleich seines LM und if_modified_since. Bei Vorhandensein (!) und Übereinstimmung schickt das Script den 304 zum Server und macht Schluss.

            Unabhängig davon aber zusätzlich: Dein serverseitiger Cache. Würde ich ganz ähnlich machen, den Feed z.B. komplett in einen Puffer schreiben, gucken was der Feed an ETag oder LM schon mitbringt. Checksum aus gesamten Content berechnen, dauert länger als einen Header zu lesen.

            Nicht FastX aber FastCGI: Script mit DB-Anbindung, die meiste Zeit und Overhead braucht der Connect. Wenn das schon läuft, geht der Rest ab wie Fußpilz :)

            Wenn kein FastCGI, dann Dateipuffer. Du regst mich an, über mein eigenes Cache-Konzept mal wieder nachzudenken, wird Zeit, meine Seiten sind langsamer geworden, kein FastCGI und alles hängt an einer DB... obwohl der gesamte Content in eine Datei gespiegelt ist, ich nutze derzeit entweder oder, das ist zwar redundant, aber daraus lässt sich noch mehr machen ;)

            Schöne Grüße aus Rheinhessen,
            Hotti

            1. Moin!

              moin,

              http://fastix.org/ - wird auch gecached. Grund: Die Seiten sind quasistatisch. Der Cache wird gelöscht wenn etwas geändert wird, beim nächsten Abruf wieder erzeugt. Statt nach 0,3 Sekunden ist die Seite nach 0,1 Sekunden ausgeliefert.

              Ha, endlich maln Foto von Dir ;)

              Neuer: http://fastix.org/Urlaub+vom+18-6-2011+bis+27-6-2011.htm

              Und auch kein Last-Mod.

              Ich kümmere mich darum. Die Nachrichtenseite wertet den Last-Mod-Header übrigens aus und verzichtet dann auf das Parsen der Feeds, nimmt die Ergebnisse dann (oder wenn der Server nicht schnell genug antwortet) auch aus einem eigenen Cache (serialisierter Array). Ich werde mir das genauer anschauen. Den Last-Mod-Header zu senden ist ja kein Problem.

              Danke für den Hinweis.

              MFFG (Mit freundlich- friedfertigem Grinsen)

              fastix

              1. Moin,

                Neuer: http://fastix.org/Urlaub+vom+18-6-2011+bis+27-6-2011.htm

                Im Lande Rübezahl.... schön, da müssen wir auch mal hinfahren ;)

                Und auch kein Last-Mod.

                Ich kümmere mich darum. Die Nachrichtenseite wertet den Last-Mod-Header übrigens aus und verzichtet dann auf das Parsen der Feeds, nimmt die Ergebnisse dann (oder wenn der Server nicht schnell genug antwortet) auch aus einem eigenen Cache (serialisierter Array).

                Idee: Eine ganz einfache Variante bestünde darin, den LM-Header einfach "durchzureichen" oder besser: Im Script den Vergleich

                IF_MODIFIED_SINCE (Dein Besucher UA) <=> Last-Modified (HTTP-Header Feed)

                Ich werde mir das genauer anschauen. Den Last-Mod-Header zu senden ist ja kein Problem.

                P. könnte es geben wenn der ETag im Spiel ist, ggf. ausschalten (.htaccess)
                FileETag None

                Ist von Fall zu Fall zu prüfen, genau hingucken ;)

                Viele Grüße,
                Hotti

          2. Om nah hoo pez nyeetz, fastix®!

            http://fastix.org/

            Im Absatz "Erfahrung:" fehlt ein "ich" (2. Satz).

            Matthias

            --
            1/z ist kein Blatt Papier. http://www.billiger-im-urlaub.de/kreis_sw.gif
            1. Moin!

              Im Absatz "Erfahrung:" fehlt ein "ich" (2. Satz).

              Danke. Erledigt.

              MFFG (Mit freundlich- friedfertigem Grinsen)

              fastix

  2. Hey fastix,

    Falls jemand Lust haben sollte, mal über

    "PHP: Einfaches Caching für Webprojekte" zu schauen und vielleicht den einen oder anderen Fehler (oder gar eine Sicherheitslücke) zu finden - es wäre nett wenn ich die Chance bekäme, da was zu verbessern.

    zuerst einmal: Sieht gut aus. Ich hätte aber einen kleinen Verbesserungsvorschlag:
    Und zwar geht's darum, dass Du ja auch die Cookie-Daten verwendest, um den Namen der Cache-Datei anzulegen. Das ist grundsätzlich auch sinnvoll, nur gibt es meiner Meinung nach eine Ausnahme: Das Session-Cookie.
    Sollte ein Session-Cookie vorhanden sein würde ja trotz gleicher Daten für jede einzelne Session eine eigene Cache-Datei angelegt werden. Ich glaube, das macht nicht so viel Sinn.
    Einfachste Möglichkeit wäre sicherlich $_COOKIE[session_name()] von der Namensvergabe auszuschließen.

    Gruß, Dennis

    1. Hi,

      Sollte ein Session-Cookie vorhanden sein würde ja trotz gleicher Daten für jede einzelne Session eine eigene Cache-Datei angelegt werden. Ich glaube, das macht nicht so viel Sinn.

      Wenn eine Session verwendet wird, dann besteht vermutlich eine hohe Wahrscheinlichkeit, dass die jeweiligen Ressourcen auch session-spezifische Daten enthalten.

      MfG ChrisB

      --
      RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
      1. Hey ChrisB,

        Sollte ein Session-Cookie vorhanden sein würde ja trotz gleicher Daten für jede einzelne Session eine eigene Cache-Datei angelegt werden. Ich glaube, das macht nicht so viel Sinn.

        Wenn eine Session verwendet wird, dann besteht vermutlich eine hohe Wahrscheinlichkeit, dass die jeweiligen Ressourcen auch session-spezifische Daten enthalten.

        das stimmt schon, vielleicht gehe ich da zusehr von meinen (bisherigen) Seiten und Anwendungen aus.
        Bei mir ist es bisher so gewesen, dass in jeder Datei die Session gestartet wird - unabhängig davon, ob ein Benutzer angemeldet ist oder nicht. Das würde beispielsweise bedeuten, dass für jeden Gast eine neue Cache-Datei mit gleichem Inhalt erstellt würde. Außerdem wird bei einigen Seiten die Session-Id "refreshed", was bedeutet, dass sogar bei einem angemeldeten Benutzer alle paar Minuten eine neue Datei erstellt werden würde.

        Ich hab das auch nur geschrieben, weil wir vor ein paar Monaten ein ähnliches Problem hatten und recht lange gebraucht haben die Ursache rauszufinden. Seht es bitte also einfach als Gedankenanstoß.

        Ich verstehe aber schon, dass das ganze (weitergedacht) wohl den Rahmen sprengt: Fastix schrieb ja auch von "einfach".

        Gruß, Dennis

        1. Moin!

          Sollte ein Session-Cookie vorhanden sein würde ja trotz gleicher Daten für jede einzelne Session eine eigene Cache-Datei angelegt werden. Ich glaube, das macht nicht so viel Sinn.

          Wenn eine Session verwendet wird, dann besteht vermutlich eine hohe Wahrscheinlichkeit, dass die jeweiligen Ressourcen auch session-spezifische Daten enthalten.

          das stimmt schon, vielleicht gehe ich da zusehr von meinen (bisherigen) Seiten und Anwendungen aus.

          Also, in meinen "produktiven" Caches wird Post, Cookie und Session nicht befragt, teilweise bilde ich die Dateinamen da auch ganz anders. In die Veröffentlichung habe ich es aufgenommen, damit nicht irgendjemand versehentlich Sicherheitslöcher schafft, weil er beim Einbau übersehen hat, dass da z.B. irgendwo das Ergebnis eines erfolgreichen Login drin steht.

          (Derlei soll ja oft vorkommen...)

          MFFG (Mit freundlich- friedfertigem Grinsen)

          fastix

          1. Hey fastix,

            Also, in meinen "produktiven" Caches wird Post, Cookie und Session nicht befragt, teilweise bilde ich die Dateinamen da auch ganz anders.

            Das dürfte meiner Meinung nach in den meisten Fällen auch die sinnvollere Variante sein.

            In die Veröffentlichung habe ich es aufgenommen, damit nicht irgendjemand versehentlich Sicherheitslöcher schafft, weil er beim Einbau übersehen hat, dass da z.B. irgendwo das Ergebnis eines erfolgreichen Login drin steht.

            Das finde ich auch gut! Nur denke ich, es wäre vielleicht hilfreicher darauf hinzuweisen. Wenn ich das Skript in der Form mit Sessions benutze ist der Caching-Vorteil ja quasi nicht vorhanden. Das fände ich insbesondere wichtig, da Du am Anfang ja explizit Sessions erwähnst:

              
            /*  
            Wichtig! Eventuell muss session_start() aus dem Skript hier her vorgezogen werden.  
            */  
            
            

            Und noch ein anderer, kleiner Punkt. Fehlt in der Zeile

              
            /* Der Name muss sicher sein, denn er wird in das Dateisystem geschrieben md5() liefert, was wir brauchen */  
                define ('FX_CACHE_FILE', FX_CACHE_DIR.md5($s).'gz');  
            
            

            nicht noch ein Punkt (.) vor dem 'gz'? Du prüfst ja später auf

              
            if ( strpos($f,'.gz') ) {  
            //...  
            }  
            
            

            Gruß, Dennis

            1. Moin!

              define ('FX_CACHE_FILE', FX_CACHE_DIR.md5($s).'gz');

              Danke. Ein echter Fehler. Behebe ich gleich.

              MFFG (Mit freundlich- friedfertigem Grinsen)

              fastix

              1. Hey fastix,

                das mit den neu hinzugefügten Konstanten finde ich sehr gut. So ist das Skript vollständiger und vorallem "stolpert" man direkt darüber, dass POST-, COOKIE- oder SESSION-Daten etwas "besonderes" sind, wenn das Skript - warum auch immer - nicht wie gewünscht funktionieren sollte oder man sich grundsätzlich mit dem Thema auseinandersetzen möchte.

                Gruß, Dennis

  3. Hello Fastix,

    und wofür ist dann dieses Rädchen gut?
    http://httpd.apache.org/docs/2.2/caching.html

    Aber nun zu Deinem Thema:

    Um tatsächlich Last vom Server zu nehmen, würde ich das Zippen bzw. Unzippen on-the-fly noch unterlassen und stattdessen zwei Files abspeichern. Das kostet zwar noch mehr Plattenplatz, erspart dem PHP-Host aber eine Menge Arbeit.

    Liebe Grüße aus dem schönen Oberharz

    Tom vom Berg

    --
     ☻_
    /▌
    / \ Nur selber lernen macht schlau
    http://bergpost.annerschbarrich.de
    1. Moin!

      Um tatsächlich Last vom Server zu nehmen, würde ich das Zippen bzw. Unzippen on-the-fly noch unterlassen und stattdessen zwei Files abspeichern. Das kostet zwar noch mehr Plattenplatz, erspart dem PHP-Host aber eine Menge Arbeit.

      Das habe ich auch schon überlegt. Das hängt nämlich sehr davon ab, ob Plattenplatz zum Problem werden könnte. Ich könnte einen Schalter einbauen. Des "fastix kleines CMS" sichert übrigens beide Varianten (normal und gezippt). Da dürfte der Plattenplatz nicht zum Problem werden.

      MFFG (Mit freundlich- friedfertigem Grinsen)

      fastix

  4. Hello,

    ... und wegen der Einbindung in vorhandene Umgebungen ist mir noch etwas eingefallen:

    Du könntest dafür auto_prepend_file und auto_append_file nutzen und ein schlankes goto im Prependfile zur Einsprungmarke im Appendfile, wenn das eigentliche Script nicht mehr ausgeführt werden soll.

    http://www.php.net/manual/en/ini.core.php#ini.auto-prepend-file
    http://it.php.net/manual/en/control-structures.goto.php

    Liebe Grüße aus dem schönen Oberharz

    Tom vom Berg

    --
     ☻_
    /▌
    / \ Nur selber lernen macht schlau
    http://bergpost.annerschbarrich.de