So widersprüchlich dieser Titel auch klingen mag - in dieser Thematik liegt
einer der vielen Schlüssel, die eine erhebliche Performancesteigerung für Webapplikationen
bietet. Ich will dies hier am Beispiel eines Online-Shops verdeutlichen, da
wohl das prädestinierte Einsatzgebiet sein sollte.
Ein regulärer Shop besteht meist aus folgenden Elementen:
- Warengruppen-Auswahl
- Übersicht der Artikel in einer Haupt- oder Unterwarengruppe
- Einzelansicht der ausgewählten Artikel
- Warenkorb (bleibt hier jedoch aufgrund der zwangsweise nötigen Dynamik außen
vor)
Wozu nun statische Seiten, wenn man ein so mächtiges Tool wie CF zur Darstellung
dynamischer Inhalte hat?
Zugriffe auf eine Datenbank sind in einer CF-Applikation meist eins der RICHTIG
engen Nadelöhre, weshalb diese gut überlegt und nur dann ausgeführt werden sollten,
wenn wirklich nötig. Ausgehend davon, daß sich die Darstellung der ersten drei
genannten Punkte generell seltener ändert, bietet es sich an, diese normalerweise
dynamischen Elemente durch statische, jedoch regelmäßig aktualisierte Seiten
zu ersetzen. Statt jedem Besucher z.B. eine aus der Datenbank generierte Artikelübersicht
für seine gewählte Warengruppe anzuzeigen, könnte man einmal täglich/stündlich/(...)
alle Artikelübersichten in statische html-Dateien schreiben, so daß aus möglicherweise
zehntausenden Anfragen an die DB einige wenige werden.
Grob gesagt gibt man hierzu die html-Inhalte, die man normalerweise an den Browser
schicken würde, nicht per Cfoutput aus, sondern schreibt sie per cffile in eine
Datei. Das Ergebnis ist identisch mit der Version, die normalerweise als vom
CF-Server generierter Content zum Browser gelangen würde, jedoch ist unser Ergebnis
eine html-Datei, welche beim direkten http-Aufruf nicht vom CF-Server interpretiert,
sondern vom Webserver stur zum Besucher geschickt wird.
Der Vorteil liegt auf der Hand: wo CF nichts tun muss, wird weder unnötige Prozessorzeit
verbraucht, noch die DB unnötig gequält. Hält man dieses Prinzip konsequent
im ganzen Shop und an allen möglichen bzw. nötigen Stellen durch, so ist das
Ergebnis eine statische Website mit dynamischem Warenkorb.
stark besuchte Shops mit einer verhältnismäßig kleinen, sporadisch zu
aktualisierenden Arikelauswahl werden hierdurch erheblich schneller, doch auch
- oder gerade - für "Mega-Stores" lohnt sich der Einsatz dieses Prinzips, da
der CF-Server so lange außen vor bleibt, bis er WIRKLICH benötigt wird.
Der Hintergrund, weshalb dieses Prinzip hier kredenze, ist - wie sollte es auch
anders sein - eine Situation aus dem "wirklichen" Leben: die prognostizierten
Zugriffszahlen eines von mir kürzlich programmierten Shops - nennen wir ihn
mal "name-eines-grossen-pda-herstellers-shop.de" :), waren viel, aber
auch wiklich erheblich sehr viel größer als erwartet, weshalb ich mir eine Lösung
überlegen musste, die Performance im grünen Bereich zu halten, zumal der Kunde
nicht auf eine größere Datenbank umstellen wollte. Schließlich habe
ich einige Templates zu statischen Seiten "degradiert" und so der Page zu einer
zweiten Jugend verholfen ;-).
So denn, nach so viel Schwafelei will ich noch eine Beispielapplikation zeigen:
Ich beschränke mich bei diesem Beispiel auf die Darstellung einer Artikelübersicht,
da das Prinzip so ausreichend verdeutlicht wird und ein jeder es auch auf andere
Bereiche portieren können wird.
Die Artikeltabelle sieht wie folgt aus:
artnr |
bez |
beschr |
preis |
123 |
Dose |
Eine Dose! |
5.00 |
124 |
Hut |
Ein Hut. |
10.00 |
125 |
Ball |
Ein Ball. |
9.00 |
Um nun eine Übersicht der Artikel zu generieren, würde man normalerweise z.B.
wie folgt vorgehen:
<!---artikeldaten holen--->
<cfquery name="getdata" datasource="#dsn#">
select bez,artnr from artikel
</cfquery>
<!---...und ausgeben--->
<cfoutput query="getdata">
<a href="artikel.cfm?artnr=#artnr#">#bez#</a><br>
</cfoutput>
Im Browser sieht dies dann wie folgt aus:
Wie weiter oben bereits erwähnt, funktioniert diese Methode einwandfrei, jedoch
wird unnötigerweise bei
jedem Aufruf die Datenbank angesprochen.
Folgende Methode schafft hier Abhilfe:
(anm: dies ist nicht die Datei, die im Browser angezeigt wird, hier wird die
anzuzeigende Datei generiert)
<!---artikeldaten holen--->
<cfquery name="getdata" datasource="#dsn#">
select bez,artnr from artikel
</cfquery>
<!---variable zur speicherung des zu schreibenden html-contents deklarieren...--->
<cfset thestring="<html><head><title>Artikelansicht</title></head><body>"
>
<!---artikelliste hinzufuegen...--->
<cfoutput query="getdata">
<cfset thestring=thestring&"<a href='artikel#urlencodedformat(artnr)#.htm'>#bez#</a><br>">
</cfoutput>
<!---string vervollstaendigen--->
<cfset thestring=thestring&"</body></html>">
<!---den fertigen string nun in eine datei schreiben--->
<cffile action="write" file="#expandpath('artikeluebersicht.htm')#" output="#thestring#">
Das Ergebnis der generierten Datei ist optisch mit dem ersten identisch:
Wir haben nun zwei augenscheinlich, die beide die Artikelliste darstellen.
Der große Unterschied jedoch ist, daß die zweite Variante nicht nur die Datenbankzugriffe
minimiert, sondern deren Ergebnis auch völlig unabhängig vom CF-Server lauffähig
ist. Den Link zur jeweiligen Artikel-Detailansicht habe von *.cfm in *.htm geändert
(dies natürlich im Hinblick auf die später vorhandene, generierte htm-Datei).
Da man zwar URL-Variablen an htm-Dateien übergeben kann, sie sie aber nicht
verarbeiten können, muss die Artikelnummer hier schon im Dateinamen hinterlegt
werden. Diese Datei ist natürlich im fertigen Shop schon statisch generiert.
Führt man dies nun in allen Teilbereichen durch, so hat man, wie der Titel des
Artikels sagt - einen dynamisch generierten, statischen Shop. Die Applikation
wird erst dann de facto dynamisch, wenn der Benutzer einen Artikel in den Warenkorb
legt, d.h. Kunden, die "lediglich" die Artikel ansehen, verursachen z.B. keine
unnötge Prozessor- und Datenbankbelastung, da der CF-Server komplett außen vor
bleibt.
Dies ist natürlich nur ein kleines Beispiel für die Verwendung statischer
Seiten, jedoch kann man eigentlich jede dynamische Applikation hiermit optimieren.
Gut geeignet ist diese Strategie auch für Newsseiten, Linklisten und was
auch immer... :)
Marcus Raphelt marcus@raphelt.de - 01.02.2001