phpbuddy.eu
-


Hinweise


Antwort
 
LinkBack Themen-Optionen Thema durchsuchen
Alt 25.06.2007, 04:11   #1
TP-Moderator
 
Benutzerbild von Rizzo
 
Registriert seit: Aug 2004
Ort: Kaiserslautern
Rizzo lebt für das TP und seine UserRizzo lebt für das TP und seine UserRizzo lebt für das TP und seine UserRizzo lebt für das TP und seine UserRizzo lebt für das TP und seine UserRizzo lebt für das TP und seine UserRizzo lebt für das TP und seine UserRizzo lebt für das TP und seine User

[Tutorial] Caching - Dynamische Seiten beschleunigen


Vorwort

Webseiten mit PHP zu erstellen ist schon eine tolle Sache. Noch besser wird es, wenn man seine ganzen Daten und Informationen aus einer Datenbank ziehen kann. Ein paar Funktionen hier, eine Datenbankverbindung da, dazu noch einige Queries und schon wird die dynamisch generierte Seite zum Besucher geschickt. Möchten jetzt 500 Leute die selbe Seite gleichzeitig sehen ( z.B. eine Produktseite in einem Onlineshop ) werden die eben erwähnten Funktionen, Datenbankverbindung und Queries eben 500 mal ausgeführt - nur um eine identische Information 500 anzuzeigen!
Was auf den ersten Blick so dynamisch wirkt, entpuppt sich schnell als eine statische Information die bei jedem Abruf wieder und wieder Ressourcen belegt und somit den Server belastet. Abhilfe kann hier das sogenannte Caching schaffen.

In diesem Tutorial möchte ich eine recht simple Variante vorstellen, damit der Leser einen Einblick bekommt wie Caching funktioniert.



Was ist Caching und wie funktioniert es?

Als Caching bezeichnet man das zwischenspeichern von Informationen bzw Daten, damit diese bei einem erneuten Aufruf sofort zur Verfügung stehen. Anders ausgedrückt bedeutet das für uns und dieses Tutorial: Wir nehmen eine dynamisch generierte Seite und wandeln sie ( temporär ) in eine statische HTML-Seite um.
Die Vorteile einer statischen Seite liegen auf der Hand:
  • Schnellerer Seitenaufbau, weil weniger Daten durch den Parser gejagd werden müssen. Statt die angeforderten Daten dynamisch zu generieren wird lediglich eine statische Seite eingebunden.
  • Der Server wird -teilweise massiv- entlastet, weil weniger Ressourcen belegt werden. Es müssen keine Variablen, Funktionen und Klassen im Arbeitsspeicher gehalten werden, die Kommunikation mit dem Datenbankserver entfällt. Somit können Aufrufe von mehr Besucher schneller bedient werden.
  • Teilweise lassen sich auch Ausfälle der Datenbank abfangen, da man Daten aus dem Cache anzeigen lässt statt sie aus der DB zu laden.
Das liest sich ja recht gut, aber leider ist nicht alles Gold was glänzt. Zu den negativen Punkten komme ich im Fazit.



Voraussetzungen

Da dieses Tutorial ausschließlich das Caching zum Thema hat sollte der Leser folgendes mitbringen
  • einfache PHP Kenntnisse
  • Erfahrung im Umgang mit Datenbanken ( auslesen, updaten, einfügen, etc. )
  • Grundlagenwissen im Umgang mit Dateien ( schreiben, lesen, löschen )

Da die Mehrheit sicherlich noch PHP 4.x.x einsetzt, werde ich mich in diesem Tutorial auch daran halten. Für PHP5 User werde ich aber auch kurz den bequemeren Weg zeigen. Die Unterschiede sind nicht wirklich gravierend, sondern ersparen einem mit PHP5 nur Schreibarbeit.


Los geht's... Caching im Einsatz

Schauen wir uns nun an wie das in der Praxis funktioniert. Die hier benutzen Datenbankzugriffe und Ausgaben sollten Basiswissen sein und werden hier nicht weiter erläutert. Als Anschauungsobjekt dient hier ein Gästebuch aus dem wir die ersten 3 Einträge auslesen möchten. Zugegeben, ein Gästebuch ist hier ein suboptimales Beispiel, aber es geht auch nur um das verdeutlichen der Caching-Technik.



Das Script ohne Caching

PHP-Code:
<?php
// Zur DB verbinden und Tabelle auswaehlen
$conid = @mysql_connect"localhost""root""" ) or die( "Fehler: MySQL nicht erreichbar!" );
mysql_select_db"gaestebuch"$conid );

// Daten aus der DB holen
$result mysql_query"SELECT `nachricht` FROM `gaestebuch` LIMIT 3" );

// Datensaetze ausgeben
while ($zeile mysql_fetch_array$result ) )
{
    echo 
nl2brhtmlspecialchars$zeile['nachricht'] ) ). "<hr>";
}

// Ressourcen freigeben und DB-Verbindung schliessen
mysql_free_result$result );
mysql_close$conid );
?>
Wie hier zu sehen ist, handelt es sich um ein ganz banales Script das sich zu einer Datenbank verbindet, 3 Einträge aus dem Gästebuch holt und diese dann in einer Schleife ausgibt. Danach werden artig die Ressourcen wieder freigegeben und alles ist bestens. Greifen jetzt aber unsere fiktive 500 Besucher gleichzeitig auf das Gästebuch zu, wird der oben stehen Code 500 Mal ausgeführt und belegt 500 Mal Ressourcen. Das geht doch bestimmt effektiver, oder?!



Das Script mit anlegen der Cache Datei

PHP-Code:
<?php
// Der interne Ausgabe-Puffer wird aktiviert
ob_start();

// Zur DB verbinden und Tabelle auswaehlen
$conid = @mysql_connect"localhost""root""" ) or die( "Fehler: MySQL nicht erreichbar!" );
mysql_select_db"gaestebuch"$conid );

// Daten aus der DB holen
$result mysql_query"SELECT `nachricht` FROM `gaestebuch` LIMIT 3" );

// Datensaetze ausgeben
while ($zeile mysql_fetch_array$result ) )
{
    echo 
nl2brhtmlspecialchars$zeile['nachricht'] ) ). "<hr>";
}

// Ressourcen freigeben und DB-Verbindung schliessen
mysql_free_result$result );
mysql_close$conid );

// Die Daten vom Puffer werden umladen
$output ob_get_contents();

// Die Cache-Datei anlegen und die Daten hinein schreiben
$datei fopen"cache/nachrichten.htm""w" );
fwrite$datei$output );
fclose$datei );

// Puffer an den Browser ausgeben und die Pufferung deaktivieren
ob_end_flush();
?>
Im Vergleich zum vorherigen Listing wurden nur wenige Zeilen ergänzt, aber die haben es in sich!

Gehen wir kurz die neuen Zeilen durch um zu sehen was dahinter steckt.

PHP-Code:
ob_start() 
Damit wird der PHP-interne Ausgabepuffer eingeschaltet. Alles was ab jetzt als Ausgabe erscheinen würde ( in unserem Script die echo-Befehle in der while()-Schleife ) landet statt auf dem Bildschirm als String im Puffer. Sofern man nicht an einer bestimmten Stelle im Script die Daten im Puffer verarbeitet, wird am Ende des Scripts automatisch ein ob_end_flush() ausgelöst und die Daten werden an den Browser gesendet.

PHP-Code:
$output ob_get_contents(); 
Mit ob_get_contents() werden die Daten aus dem internen Puffer an die Variable $output übergeben, wo sie auf eine weitere Verarbeitung warten.

PHP-Code:
$datei fopen"cache/gaestebuch.htm""w" );
fwrite$datei$output );
fclose$datei ); 
Dieser Code sollte bekannt sein, da hier lediglich eine HTML-Datei im Ordner cache angelegt und der Inhalt von $output darin abgelegt wird.
Hinweis: Der Ordner cache muß bereits existieren und Schreibrechte besitzen!

PHP-Code:
ob_end_flush(); 
Diese Zeile sendet den Puffer an den Browser, damit dort nicht einfach eine weiße Seite angezeigt wird. Anschliessend wird die Pufferung beendet und der Arbeitsspeicher freigegeben.

Na toll, jetzt erzeugen/überschreiben wir also jedesmal eine Datei wenn jemand die Seite aufruft. Irgendwie ist das aber noch nicht so das Gelbe vom Ei!?
Was uns jetzt noch fehlt ist die Möglichkeit...:
  • zu prüfen ob beim Seitenaufruf bereits eine entsprechende Cache-Datei existiert. Falls Nein, wird eine erzeugt. Falls Ja, dann...
  • die Cache-Datei anzeigen lassen, statt erst eine dynamische Seite zu generieren.
  • festzustellen ob die Cache-Datei überhaupt noch aktuell ist oder ob es nicht bereits eine aktuellere Version geben sollte.



Das fertige Script

PHP-Code:
<?php
// Pfad und Name der Cache-Datei und Gueltigkeitsdauer in Sekunden
$CacheDatei "cache/gaestebuch.htm";
$CacheDauer 3600;

// Pruefen ob eine entsprechende Cache-Datei bereits existiert
// und ob sie noch gueltig ist
if (file_exists$CacheDatei ) &&
   (
time() - filemtime$CacheDatei )) < $CacheDauer )
{
    
// Statt die Seite dynamisch generieren zu lassen wird die
    // statische HTML-Datei eingebunden
    
include( $CacheDatei );
    exit();
}

// Der interne Ausgabe-Puffer wird aktiviert
ob_start();

// Zur DB verbinden und Tabelle auswaehlen
$conid = @mysql_connect"localhost""root""" ) or die( "Fehler: MySQL nicht erreichbar!" );
mysql_select_db"gaestebuch"$conid );

// Daten aus der DB holen
$result mysql_query"SELECT `nachricht` FROM `gaestebuch` LIMIT 5" );

// Datensaetze ausgeben
while ($zeile mysql_fetch_array$result ) )
{
    echo 
nl2brhtmlspecialchars$zeile['nachricht'] ) ). "<hr>";
}

// Ressourcen freigeben und DB-Verbindung schliessen
mysql_free_result$result );
mysql_close$conid );

// Die Daten im Puffer umladen
$output ob_get_contents();

// Die Cache-Datei anlegen und die Daten hinein schreiben
$datei fopen$CacheDatei"w" );
fwrite$datei$output );
fclose$datei );

// Puffer an den Browser ausgeben und die Pufferung deaktivieren
ob_end_flush();
?>
Hinzugekommen ist nur der obere Teil des Scripts. Zuerst setzen wir den Pfad und Namen zur Cache-Datei, dann noch die Zeit in Sekunden wie lange die Cache-Datei als gültig angesehen wird. Ist die Datei älter als erlaubt, wird beim nächsten Aufruf der Seite die Cache-Datei neu generiert.

PHP-Code:
if (file_exists$CacheDatei ) &&
   (
time() - filemtime$CacheDatei )) < $CacheDauer )
{
    
// Statt die Seite dynamisch generieren zu lassen wird die
    // statische HTML-Datei eingebunden
    
include( $CacheDatei );
    exit();

In der IF-Anweisung wird geschaut ob die Cache-Datei existiert und ob sie noch gültig ist. Falls nicht, wird der Block übersprungen und eine neue Datei erzeugt. Falls aber alle Kriterien zutreffen, wird einfach nur die statische HTML-Datei eingebunden und das Script per exit(); verlassen. Wir sparen uns hier also die komplette DB-Kommunikation und das erneute anlegen der Cache-Datei. Somit wird nur einmal alle 3600 Sekunden ( 1 Stunde ) eine Seite generiert und an unsere 500 Besucher ausgegeben, statt 500 Mal die Datenbank zu kontaktieren um die Seite dynamisch erzeugen zu lassen!



Das Script für PHP 5 User

Mit PHP 5 kamen einige neue Funktionen hinzu, die einem Schreibarbeit abnehmen. Dieser PHP 4 Block...
PHP-Code:
// Die Daten im Puffer umladen
$output ob_get_contents();

// Die Cache-Datei anlegen und die Daten hinein schreiben
$datei fopen$CacheDatei"w" );
fwrite$datei$output );
fclose$datei );

// Puffer an den Browser ausgeben und die Pufferung deaktivieren
ob_end_flush(); 
...läßt sich verkürzen indem man statt dessen...

PHP-Code:
file_put_contents$CacheDateiob_get_flush() ); 
...diesen Einzeiler verwendet.



Das Fazit

Wie man sieht läßt sich mit sehr wenigen Zeilen Code eine Verbesserung einbauen die auf stärker frequentierten Seiten doch zu erheblichem Geschwindigkeitszuwachs beitragen kann. Die Entlastung für den Server ist enorm und auch die Besucher bekommen schneller die angeforderte Information auf den Bildschirm.

Bevor jetzt alle anfangen ihre Scripts umzuschreiben möchte ich noch kurz auf die eingangs erwähnten negativen Punkte dieses Verfahrens eingehen.
Für kleine(re) Seiten lohnt sich der Aufwand kaum, da der Performancegewinn minimal ist. Für größere Projekte kann es sich sehr wohl lohnen aber man sollte bedenken, daß der zusätzlich benötigte Platz auf dem Server enorm sein kann. Immerhin müssen die Daten doppelt vorhanden sein, einmal in der DB, einmal als HTML-Variante. Es empfiehlt sich auch ein eigener Server, da das Dateisystem bei Shared Hosting i.d.R. unter einer recht hohen Belastung steht und der Performancegewinn durch lange Festplatten-Zugriffszeiten wieder zunichte gemacht wird. Letztendlich findet man das aber nur in einem praktischen Testlauf heraus.

Das oben gezeigte Verfahren dient nur als Einblick. Effektiv wird es natürlich erst, wenn man ein Projekt von Grund auf mit Cache-System plant. Letztendlich bleibt es der Phantasie des User überlassen, auf welche Art so ein Cache-System eingebaut werden soll.

Ich hoffe dieses kleine Tutorial ist dem ein oder anderen von Nutzen und wünsche ein erfolgreiches Caching

Zum Abschluß gibt es noch die...



Link-Übersicht

Benutzte PHP-Funktionen
__________________
#.Viele Grüße, Andreas
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
.
Rizzo ist offline   Mit Zitat antworten


Alt 30.06.2007, 19:07   #2
TP-Member
 
Benutzerbild von dichter
 
Registriert seit: Feb 2005
dichter macht alles soweit korrekt
Das hört sich sehr ja nützlich an. :-)
super erklärt, vielen dank!
__________________
hi
dichter ist offline   Mit Zitat antworten
Alt 16.08.2007, 15:48   #3
TP-Junior
 
Registriert seit: Mar 2007
Ort: Berlin
ronsn macht alles soweit korrekt
Danke für dieses Beispiel.
Ich hab mir dazu auch Gedanken gemacht und möchte mal wissen, wie ihr darüber denkt.

In deinem Beispiel regenerieren wir die Datei nach mindestens einer Stunde.
Da sich dein Beispiel nur auf das Lesen von Contents bzw. die Ausgabe des Contents, aber nicht auf das Schreiben, bezieht ist es bei einem Gästebuch wohl nicht schlimm, wenn erst nach einer Stunde der Content neu geladen würde.
Wenn ich mir jedoch ein Forum vorstelle, müssten die User eine Stunde warten, bis neue Beiträge angezeigt würden.
Was kann man da nun machen? Die Zeit zwischen der Regenerierung verkürzen? Da stell ich mir wieder ein Forum vor. Die User warten trotzdem noch eine gewisse Zeit. Aber würden wir die Zeit zu niedrig einstellen, dann könnten wir ja gleich wieder auf die altbewährte Methode zurückgreifen.

Mit dem Wissen, das Server sehr gut darin sind statische Dateien einfach wiederzugeben, würde ich ungerne auf das Cachen verzichten.
Statistisch gesehen, greifen die Besucher einer Seite weniger schreibend, als lesend auf eine Seite zu, was noch ein Grund ist, die Dateien zu cachen.

Daher habe ich mir überlegt, ob es nicht effektiver wäre, wenn man die Datei nur dann regeneriert, wenn neue Daten in der Datenbank liegen.
Dazu kann man jedesmal, wenn ein neuer Eintrag getätigt wird eine Datei erzeugen, in welcher Informationen stehen, welche Daten dazugekommen sind bzw. geändert worden sind. Es soll also nur eine Informationsdatei erzeugt werden.
Und hier kommt dein Beispiel wieder.
Anstatt hier nach der Zeit zu gehen, können wir prüfen, ob eine Informationsdatei vorhanden ist. Wenn ja, dann lese diese aus und schaue, welche Daten aktualisiert wurden.
In diesem Fall, wird eine Neue Cache-Datei angelegt und die Informationsdatei gelöscht.
Wenn keine Informationsdatei vorhanden ist, wird die alte Cache-Datei ausgegeben.

In wechler Art man eine Informationsdatei anlegt, oder ob man leere Informationsdateien mit verschiedenen Namen erzeugt, will noch erörtert werden. Immerhin habe ich gelesen, dass die Funktion is_file() sehr schnell sei, womit ich lieber ein System mit unterschiedlich nominierten Dateinamen bevorzugen würde.

Geändert von ronsn (16.08.2007 um 15:55 Uhr). Grund: Qualitätssicherung
ronsn ist offline   Mit Zitat antworten
Alt 20.09.2007, 20:22   #4
TP-Senior
 
Benutzerbild von Andy010
 
Registriert seit: Mar 2003
Ort: Bamberg
Andy010 macht alles soweit korrekt

Cache-Datei löschen


Hi,

würde es nicht reichen die Cache-Datei einfach zu löschen bei neuem Eintrag? So könnte man auch die Cache-Dauer ganz weglassen!

Gruß Andy
__________________
Schönen Gruß aus Franken!
Andy010 ist offline   Mit Zitat antworten
Alt 20.09.2007, 21:14   #5
TP-Veteran
 
Benutzerbild von manuelito
 
Registriert seit: Sep 2002
Ort: Winterthur
manuelito hilft, wo's gehtmanuelito hilft, wo's gehtmanuelito hilft, wo's geht
Jep, man muss das Cachefile einfach neu generieren, sobald ein Inhalt geändert wird. Das ist relativ einfach bei bei diesem Beispiel, bei komplexeren Inhalten wird es dann wieder schwierig, weil man die Zusammenhänge unter verschiedenen Inhalten kennen muss, die in eine cachbare Seite integriert werden. Ist aber alles machbar
__________________
Metal klingt am besten, wenn man taub ist.
manuelito ist offline   Mit Zitat antworten
Alt 21.09.2007, 00:50   #6
TP-Special Mod
 
Benutzerbild von steffenk
 
Registriert seit: Feb 2005
Ort: Haan / NRW
steffenk lebt für das TP und seine Usersteffenk lebt für das TP und seine Usersteffenk lebt für das TP und seine Usersteffenk lebt für das TP und seine Usersteffenk lebt für das TP und seine Usersteffenk lebt für das TP und seine Usersteffenk lebt für das TP und seine Usersteffenk lebt für das TP und seine User
Je komplexer das System wird (z.B. mit Forum, Gästebuch etc) sollte mans sich ein mehrschichtiges Cache bauen. So kann eine Seite aus verschiedenen Objekten bestehen:
- cached static Data
- noncached dynamic Data

So kann man die Seite aus mehreren Teilen zusammensetzen. Ein Löschen der Cachedatei ist eine brutale Methode, die Seite muss komplett neu gerendert werden. Mit der Mehrschichtigkeit muss man nur die Teile neu generieren, die sich verändert haben.
__________________

Typo3 · MySQLDumper · dislabs
·
manche Mühlen mahlen schneller ...
"Ich habe Rücken"
Horst Schlämmer
steffenk ist offline   Mit Zitat antworten
Alt 21.09.2007, 17:28   #7
TP-Senior
 
Benutzerbild von Andy010
 
Registriert seit: Mar 2003
Ort: Bamberg
Andy010 macht alles soweit korrekt
Und den dynamischen Teil könnte man bei der Änderung gleich rendern. Hört sich nicht mal so kompliziert an. Warum macht man das nicht von grundauf schon so?
Für den Server dürfte es wohl auch keine größere Belastung sein.
__________________
Schönen Gruß aus Franken!
Andy010 ist offline   Mit Zitat antworten
Alt 21.09.2007, 19:15   #8
TP-Special Mod
 
Benutzerbild von steffenk
 
Registriert seit: Feb 2005
Ort: Haan / NRW
steffenk lebt für das TP und seine Usersteffenk lebt für das TP und seine Usersteffenk lebt für das TP und seine Usersteffenk lebt für das TP und seine Usersteffenk lebt für das TP und seine Usersteffenk lebt für das TP und seine Usersteffenk lebt für das TP und seine Usersteffenk lebt für das TP und seine User
ist auch nicht so kompliziert, das Konzept muss halt stimmen. Und das setzt vorraus, das man Objekte für die Seite definiert. Jedem Objekt gibt man die Eigenschaft für cached/noncached mit, ein PageGenerator geht das Array der Objekte durch und holt sich die aus dem Cache oder fordert das Rendern an.

Für den Server ist das ganz klar eine Entlastung.
__________________

Typo3 · MySQLDumper · dislabs
·
manche Mühlen mahlen schneller ...
"Ich habe Rücken"
Horst Schlämmer
steffenk ist offline   Mit Zitat antworten
Antwort

  Aktuelles Thema
  TP Hilfe Forum > Web-Editoren & Coding > Traum-Dynamik > Workshops und Tutorials
[Tutorial] Caching - Dynamische Seiten beschleunigen [Tutorial] Caching - Dynamische Seiten beschleunigen
« [MySQL] nutzen und lernen | [MySQL] INSERT oder UPDATE ? »

Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an
Gehe zu


Alle Zeitangaben in WEZ +2. Es ist jetzt 15:27 Uhr.

Powered by: vBulletin Version 3.7 (Deutsch)
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd. / Search Engine Friendly URLs by vBSEO 3.2.0 ©2008, Crawlability, Inc.
Traum-Projekt.com | Suchen | Archiv | Impressum | Kontakt | | | Nach oben |



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67