Serverlast entgegenwirken (3) – nutze deinen Webserver

Es gibt bekanntermaßen viele Möglichkeiten, die Performance der eigenen Website zu optimieren. Sei es die Verwendung eines anderen Webservers oder der Einsatz mehrerer Server mittels Load-Balancing (hier eine Information am Rande: Strato will bis Ende des Jahres Hardware-Load-Balancing-Systeme ins Produktfolio mitaufnehmen).

Doch nicht immer kann man den Standard-Webserver ersetzen oder hat die finanziellen Mittel für eine kleine Serverfarm zur Verfügung. Deshalb ist die Frage, wie man trotzdem ans Ziel kommen kann. Die einfachste Lösung ist dabei die beste: Nutze deinen Webserver.

Das Potential des Webservers ausnutzen:

Bekannt sollte sein, dass der Web-Server für die Auslieferung von Seiten an den Benutzer verantwortlich ist. Deshalb sollte optimalerweise auch lediglich dieser Inhalte ausgeben. Scriptsprachen wie Ruby, PHP oder auch Perl sind hier immer langsamer als der Webserver an sich. Dieses Wissen kann man nun ausnutzen und im eigenen Projekt einsetzen:

Caching des Webservers

Die meisten aktuellen Seiten werden dynamisch erstellt und verwenden eine Script-Sprache wie PHP, Perl oder Ruby oder setzen auf Java und Co. Alle haben aber eins gemeinsam: Sie erstellen die Seiten bei jedem Aufruf neu. Das ist natürlich sehr rechenintensiv und eigentlich unnötig, weshalb größere Seiten die Erstellung einer Seite zwischenspeichern (cachen) und dann nur noch diesen Cache abrufen. Hierzu bieten auch alle oben genannten Sprachen entsprechende Mechanismen an.

Doch es geht besser, denn für die Auslieferung ist optimalerweise der Webserver zuständig. Eine sehr geschickte Funktion bietet hierzu der Webserver lighttpd, denn er ist in der Lage, eine Seite aus mehreren Einzel-Teilen zusammen zu bauen, so wie es auch in PHP möglich ist.


output.content-type text/html
output.include _cache.html
trigger.handler index.php
trigger.if file.mtime("daten1.tmpl") > file.mtime("_cache.html")
trigger.if file.mtime(daten2.tmpl") > file.mtime("_cache.html")
trigger.if file.mtime("content.html") > file.mtime("_cache.html")

Was macht dieser Code: Er sendet die Datei _cache.html an den Benutzer, es sei denn, einer der drei Bedingungen treffen zu (eine Datei ist neuer). Dann wird die Datei index.php aufgerufen.

Dieser Code kann natürlich auch auf PHP portiert werden. Jedoch ist der Aufruf-Parsen-Ausführen-Prozess nicht zu unterschätzen, so dass unter gegebener Einstellung eine Leistungsverbesserung um den Faktor 69 erreicht werden kann, während die PHP-Lösung lediglich eine Verbesserung um Faktor 1,5 schafft.

Gleich sieht es natürlich mit einfachen Includes aus, wie sie in WordPress und Co. verwendet werden:


< ?php readfile("header.html"); readfile("body.html"); readfile("footer.html"); ?>

wird zu


output.content-type text/html
output.include header.html
output.include body.html
output.include footer.html

Auf diese Weise muss PHP nicht extra ausgeführt werden, denn für die Funktionen ist PHP völlig unterfordert und der Lade-Aufwand ist nicht gerechtfertigt.

Ein entsprechendes Modul für den Apache ist mir leider nicht bekannt.

Ausliefern von Dateien – sendfile nutzen

Der Kernel bestimmter Betriebssysteme enthält den Systemaufruf sendfile. Er ermöglicht den direkten Versand einer Datei über das Netzwerk, was erheblich schneller geht als das Öffnen, Lesen und Ausgeben. Die Unterstützung ist im Apache standardmäßig aktiv und auch in lighttpd steht sie zur Verfügung. Nun kann mann sendfile leider nicht direkt nutzen. Mittels Header-Manipulation geht das aber wunderbar. Dazu rüstet man den Apache nun mit dem Modul mod_xsendfile aus, lighttpd unterstützt diese Funktion von Haus aus.

Der Webserver erkennt nun einen bestimmten Header (X-SENDFILE), ignoriert daraufhin die weitere Ausgabe der Datei und sendet sofort die angegebene Datei mittels sendfile. Dies könnte wie folgt aussehen:


< ?php if ($login) { header("X-Sendfile: $somefile"); //falls der Webserver hier nicht reagiert... header("Content-Type: application/octet-stream"); header("Content-Disposition: attachment; file=\"$somefile\""); exit; } ?>
Permission denied

Der Vorteil dieser Herangehensweise liegt auf der Hand. Anstatt eine Datei (die evtl. 200 MB groß sein mag) zu öffnen, in eine Variable zwischenzuspeichern und dann wieder auszugeben wird der Dateiversand direkt vom Webserver ausgeführt. Bei einigen parallelen Zugriffen senkt man dabei massiv die Serverlast. Ein weiterer Vorteil: PHP (oder eine andere Scriptsprache) ist nicht mehr für den Versand verantwortlich. So kann es auch zu keinen Zeit-Problemen kommen, die durch die Scriptsprache verursacht wird.

Eingesetzt wird die Technik offenbar bei sevenload, wie im aktuellen PHP-Magazin zu lesen ist. Der Grund ist offensichtlich: Die Dateien können aufgrund Namens-Überschneidungen nicht im Original gespeichert werden und müssen deshalb abstrakte Namen bekommen. Mittels entsprechenden Quer-Bezügen kann die entsprechende Datei dann aber schnell ausgewählt werden. Der Dateiversand wird schließlich direkt vom Webserver durchgeführt.

Ein Gedanke zu „Serverlast entgegenwirken (3) – nutze deinen Webserver

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.