Webseiten-Tuning mit Squid
Artikel erschienen in Swiss IT Magazine 2008/06
Als sich die meisten Anwender noch mit Analog- oder ISDN-Modem ins Internet einwählten, dienten möglichst nahe beim Anwender positionierte Proxy-Server vor allem dazu, die Menge des zu transferierenden Traffic zu senken. Schliesslich sparte jedes Kilobyte, das sich nicht durch die Telefonleitung zwängen musste, nicht nur Zeit, sondern auch Geld. Bei heutigen Breitbandverbindungen lohnt sich dies aber nicht mehr, zumal Proxy-Server bei dynamischen Webseiten kaum noch auf brauchbare Hit-Raten kommen. So sind Proxy-Server auf Anwenderseite meist noch dazu da, missliebigen Content zu verbannen.
Dagegen wird durch die immer stärkere Verbreitung von dynamischen Webseiten ihr Einsatz als sogenannter Reverse Proxy auf Seite des Webseitenbetreibers interessant. Denn wenn jeder Besucher eine Seitenanfrage zuerst an den Reverse Proxy stellt anstatt den Webserver, kommt der Reverse Proxy problemlos auf hohe Hit-Raten. Damit lässt sich zwar keine Bandbreite sparen, dafür aber der Webserver (sowie allfällige Applikations- und Datenbankserver) entlasten.
Denn solange die Inhalte gültig sind, werden sie vom Reverse Proxy ausgeliefert und die anderen Server nicht mit der Anfrage behelligt. Sie brauchen die Inhalte somit nur noch neu zusammenzustellen, wenn die alten abgelaufen sind oder neue hinzukommen. Je nach Art der Inhalte und ihrer Lebensdauer kann auf diese Weise der Arbeitsaufwand beim Webserver und Co. unter Umständen dramatisch verringert werden.
Caching (und damit auch dem Reverse Proxy) wird oftmals mit dem Vorbehalt begegnet, dass dies zur Auslieferung veralteter Inhalte führe – was natürlich nicht im Sinne des Seitenbetreibers ist. Allerdings entspricht dies nur bedingt der Wahrheit. Selbstverständlich ist es möglich, mit einem Reverse Proxy wie mit jedem anderen Caching-System veraltete Inhalte auszuliefern. Mit der richtigen Einstellung des Reverse Proxy kann dies aber verhindert oder die Verzögerungen auf einen akzeptablen Zeitraum verringert werden. Denn am Ende ist Caching immer ein Kompromiss zwischen veralteten Inhalten und ressourcenhungriger Dynamik. Deshalb gilt es abzuwägen, was wie lange zwischengespeichert werden kann und wie mit intelligenter Cache-Steuerung dieser Zeitraum möglichst weit ausgedehnt werden kann.
Die Steuerung des Caching-Verhaltens erfolgt hauptsächlich mit zwei HTTP-Headern: Cache-Control und Expires. Während Expires festlegt, bis zu welchem Datum und Uhrzeit ein Dokument maximal zwischengespeichert werden darf, definiert Cache-Control (Teil von HTTP 1.1), wie lange ein Dokument maximal zwischengespeichert werden darf. Der Vorteil von der Arbeitsweise von Cache-Control liegt darin, dass es nicht darauf angewiesen ist, dass bei den Caches die Uhr richtig geht. Dies ist vor allem dann von Bedeutung, wenn die Cache-Zeiten im Minuten- oder gar Sekunden-Bereich liegen.
Für statische Inhalte lassen sich die Caching-Perioden in der Regel über die Webserver-Konfiguration steuern. Apache bringt dazu beispielsweise das Modul
mod_expires mit, das es erlaubt, Caching-Perioden nach MIME Type zu konfigurieren. Die Direktive ExpiresByType text/html "access plus 7 days" legt beispielsweise fest, dass HTML-Dateien für 7 Tage nach dem ersten Abruf zwischengespeichert werden können. Die Header Expires und Cache-Control werden dabei von mod_expires automatisch gesetzt.
Mit dem Setzen der Header hat man die für das Caching nötigen Vorkehrungen seitens der Webseite vorgenommen. Nun gilt es, den Reverse Proxy vor den Webserver zu spannen, da die Webseiten sonst nur im Browser Cache landen und trotzdem für jeden Besucher ausgeliefert werden müssen.
Auch wenn Webserver in der Regel Unterstützung für die Einrichtung von Reverse Proxies mitbringen, lohnt es sich, statt dessen auf eine spezialisierte Software wie Squid zu setzen. Squid ist nicht nur auf den Betrieb als Cache ausgerichtet, sondern bringt auch eine Vielzahl an Kontrollmöglichkeiten und Clustering-Fähigkeiten mit.
Die Beispielkonfiguration (siehe Kasten) geht davon aus, dass sich Squid und der Webserver auf derselben Maschine befinden. Zu diesem Zweck wurde Apache auf das Loopback Interface (127.0.0.1) an Port 8080 gehängt. Den Platz am öffentlichen Port 80 erhält stattdessen Squid, was mit der Zeile http_port geregelt wird. Mit der Direktive cache_peer wird Squid gesagt, an welche IP und Port er die Anfragen, die er selber nicht beantworten kann, weiterreichen muss. Mit cache_dir wird Squid angewiesen, die zwischenzuspeichernden Objekte, die nicht in den RAM passen, in /var/spool/squid3 abzulegen und maximal 1 GB Plattenplatz zu belegen. Die letzten vier Zeilen erlauben zudem Anfragen für die Domains squid1.local und squid2.local. Alle anderen Anfragen werden ignoriert.
Hat man diese Minimalkonfiguration in die Squid-Konfigurationsdatei squid.conf eingetragen, braucht man die Server nur noch neu zu starten und man sollte die beiden Domains squid1.local und squid2.local statt über Apache nun über Squid erreichen können.
Wer dabei die Header, beispielsweise mit der Firefox-Extension Live HTTP Headers (livehttpheaders.mozdev.org) mitprotokolliert, wird nun zwei neue Header-Zeilen entdecken: X-Cache: MISS from localhost und Via: 1.0 localhost (squid/3.0.PRE5). Diese zeigen einerseits, dass die Seiten via Squid angeliefert wurden und ein sogenannter Cache Miss verursacht wurde. Dies bedeutet, dass Squid das Objekt nicht gefunden hat und statt- dessen den Parent (also Apache) nach dem Originaldokument gefragt hat. Ruft man nun ein zweites Mal dieselbe Seite auf, wird aus dem Cache Miss ein Hit – sofern die Inhalte noch gültig sind.
Dann liefert Squid die Inhalte direkt aus und fragt den Parent nicht mehr an. Insofern wird man im Apache Log auch keine Spur der Anfrage finden (siehe Grafik). Aber Achtung: Wer auf den Reload-Knopf drückt, wird keinen Hit, sondern einen Miss erhalten. Warum? Wenn man auf den Reload-Knopf drückt, setzt der Browser Cache-Control: max-age=0; in die Anfrage ein, was den Reverse Proxy dazu zwingt, beim Parent zu prüfen, ob die Inhalte weiterhin gültig sind. Wer dies verhindern will, muss die Squid-Konfiguration so anpassen, dass die Cache-Control-Header seitens des Clients unterdrückt werden.
Was Squid genau tut, also welche Daten er beim Parent anfordert und welche Daten er von wo (Disk, Memory) ausliefert, lässt sich detailliert von den Squid-Logs auslesen. Diese lassen sich vielfältig konfigurieren und anhand der verschiedenen Codes, die für Hits, Misses und die Datenquellen verwendet werden, filtern und beispielsweise in RRDtool einspeisen. Auf diese Weisen lassen sich aufschlussreiche Grafiken generieren, die bei der Optimierung des Caching helfen können. Zudem werden die Logs als Ersatz für die Webserver-Logs benötigt, sofern man die IP-Adressen und Herkunft der Besucher auswerten will. Denn bei der Verwendung eines Reverse Proxy kommen für den Webserver alle Anfragen nur vom Proxy Server. Dies kann ausserdem ein Problem für einige Applikationen bedeuten, die mit Redirects und Port-Nummern operieren und die unter Umständen die falschen Header an den Benutzer senden. Es gilt also, vor einem Einsatz eines Reverse Proxy diesen und die Webapplikation auf optimales Zusammenspiel zu testen.
Die hier vorgestellten Szenarien beleuchten nur das absolute Minimum der Möglichkeiten, die einem Squid als Reverse Proxy bietet. So existiert neben einer Vielzahl von erschöpfend dokumentierten Konfigurationsoptionen zur Feineinstellung auch die Möglichkeit, Squid als Load Balancer zu nutzen oder Cache-Hierarchien anzulegen. Ausserdem lassen sich nebst HTTP und HTTPS weitere Protokolle wie FTP durch Squid schleusen.