Plesk und Varnish

Schnellere Webseiten durch Caching? –> Varnish ist eine Lösung. Klein, schlank und unter Linux praktisch universell verfügbar. Doof nur, dass man dafür den Port des Webservers verstellen muss – und Web-Präsenzen, die mit dem Plesk Panel von Parallels geführt werden, dies nicht vorsehen.

Hier ist die Bastelanleitung, wie ich den Trick in einer Nacht hinbekommen habe:

Ausgangslage

Wie erwähnt handelt es sich um eine Webseite mit Plesk Panel, genau genommen mit Plesk Panel 11.0. Der Doku nach müsste es allerdings genauso mit Panel 11.5 funktionieren. Der Server läuft auf CentOS.

Erste Schritte

Zunächst kann man einfach über yum varnish installieren:

sudo yum install varnish

Dann folgt einer der wichtigsten Schritte überhaupt:

Machen Sie / mach ein zuverlässiges vorher-Backup des gesamten Servers. Denken Sie daran: keiner will ein Backup – alle wollen das Restore.

Wir greifen mit den nächsten Schritten so tief in die Konfiguration des Servers ein, dass es „innerhalb“ der bestehenden Installation unter Umständen schwierig wird, die Ausgangssituation wiederherzustellen. Beim Erarbeiten dieser Anleitung war die Webseite immer wieder für ein paar Minuten versehentlich offline, bis ich den entscheidenden „Kniff“ entdeckt hatte. (Habe ich schon erwähnt, dass ich die Änderungen nachts durchgeführt habe, um die Besucher der Webseite möglichst wenig zu stören?)

Eine Architektur-Entscheidung

Natürlich soll varnish ganz „normal“ auf Port 80 auf Anfragen warten und diese Anfragen dann an den Apache weitergeben. Dazu muss Apache auf einen anderen Port „umziehen“.

Legen Sie fest, auf welchen anderen Port Apache umgestellt werden soll. Zum Beispiel auf 4080. Dabei sollten Sie beachten, dass keine anderen Prozesse diesen Port belegen. Mit

sudo netstat -tpan

rufen Sie die Liste der aktuell belegten TCP-Ports auf und bekommen sogar die Liste der zugehörigen Programme mitgeliefert.

Varnish-Basiskonfiguration

Mit dieser Information können Sie die Basis-Konfiguration für varnish festlegen. Je nach Distribution können die Konfigurationsdateien an verschiedenen Stellen liegen. Zwei davon gilt es, zu überprüfen:

In /etc/sysconfig/varnish sollte die Konfigurationsvariante 3 aktiv sein. Der entsprechende Abschnitt sollte etwa so aussehen


## Alternative 3, Advanced configuration
#
# See varnishd(1) for more information.
#
# # Main configuration file. You probably want to change it :)
VARNISH_VCL_CONF=/etc/varnish/default.vcl

Entscheidend ist das „#“, das Sie vor dem VARNISH_VCL_CONF NICHT sehen. (Sonst ist die Zeile auskommentiert)

Die andere Datei ist natürlich /etc/varnish/default.vcl (oder worauf auch immer die Konfigurationsvariable oben zeigt).

Für den Einstieg kann man der Anleitung hier folgen und einfach nur eintragen:


backend default {
.host = "127.0.0.1";
.port = "4080";
}

Irgendwoher muss Varnish die Webseiten ja auch bekommen – mit dieser Konfiguration ist das localhost auf Port 4080 (oder wofür Sie sich eben entschieden haben). Da gibt es noch viel zu justieren, doch für den Einstieg ist das gut genug.

Apache ListenPort umziehen

Nun zum schwierigsten Teil des Projekts: Den ListenPort von Apache umziehen.
Plesk Panel generiert die Konfiguration für Apache immer wieder neu, darum ist es wichtig, die neue Portnummer sauber mit Plesk Panel zu verzahnen. Am Beispiel apache+nginx wird dies in der Plesk-Dokumentation gelöst, indem die man die Templates für die Konfiguration ändert, die Datenbankabfrage entfernt und stattdessen die Portnummern fest verdrahtet einsetzt. (siehe hier).

Das kann man sicher so machen, doch irgendwie ist das nicht im Sinne des Erfinders: Der HTTP-Port wird extra aus eiener Datenbank gelesen, damit er veränderbar wird, und um ihn dann am Ende zu verändern, ersetzt man die Datenbankabfrage durch eine feste Portnummer? Und wo taucht die Portnummer noch überall auf? Da ist es doch sinnvoller, die neue Portnummer in die Datenbank zu schreiben.

Hier habe ich gefunden, wie das geht:


mysql -uadmin -p$(sudo cat /etc/psa/.psa.shadow) -D psa -e'replace into misc (param, val) values ("http_port", 4080);'

Man beachte das unterstrichene sudo oben, das im Original so nicht steht: mysql verwendet ohnehin sein eigenes Berechtigungswesen, doch das Auslesen des psa-Passwortes ist root vorbehalten, darum gehört das sudo in die Klammer.

Das war der Schritt, der mir am meisten Kopfzerbrechen macht, da ich nicht genau weiß, wie dieser Datenbankeintrag verwendet wird.

Doch der eigentliche Haken kam erst noch.
Vor allem ist wichtig, dass die nächsten Schritte unmittelbar hintereinander ausgeführt werden. Der nächste Schritt führt zu einer „kaputten“ Konfiguration.

Jedenfalls können wir jetzt die komplette Plesk-Panel-Konfiguration neu generieren:


/usr/local/psa/admin/bin/httpdmng --reconfigure-all

Achtung:

  1. Je nach Serverleistung kann das durchaus ein paar Minuten dauern
  2. Dieser Schritt ist bei mir einmal hängengeblieben. Das macht nichts, ich konnte ihn ein paar Mal laufen lassen und habe schließlich das gewünschte Ergebnis erhalten
  3. Jetzt ist die Apache-Konfiguration kaputt. Der Umzug des Apache-Servers auf den neuen Port benötigt noch einen weiteren Schritt.

… denn aus Gründen, die sich mir verschließen, wird die Hauptkonfiguration für Apache nicht neu generiert. In der /etc/httpd/conf/httpd.conf muss der Listen Port noch manuell umgestellt werden.

Der entsprechende Abschnitt sieht in der Standardkonfiguration so aus:


# Change this to Listen on specific IP addresses as shown below to
# prevent Apache from glomming onto all bound IP addresses (0.0.0.0)
#
#Listen 12.34.56.78:80
Listen 80

Natürlich muss auch hier die neue Port-Nummer eingetragen werden.

Meine Hoffnung ist, dass diese Datei überhaupt nicht generiert wird und so diese manuelle Änderung auch von Plesk Panel nie überschrieben wird – aber sicher kann ich mir dabei leider nicht sein.

Damit ist die Umstellung der Konfiguration vorläufig abgeschlossen. Alles müsste im Moment noch wie vor den Änderungen laufen. Es wird Zeit, die Server neu zu starten:


sudo service varnish restart

sudo service httpd restart

Erster Test

Für einen ersten Test genügt curl: Hier ist beispeilhaft die Ausgabe von curl -I <url>


HTTP/1.1 200 OK
Server: Apache
Vary: User-Agent,Accept-Encoding
Content-Type: text/html; charset=UTF-8
Content-Length: ...
Date: ...
X-Varnish: 295406203 295406198
Age: 112
Via: 1.1 varnish
Connection: keep-alive

Die Header-Zeilen X-Varnish und Via zeigen, dass die Webseite jetzt über varnish läuft.

So weit, so gut. Jetzt wird es Zeit, die Site gründlich zu testen, um sicherzugehen dass die gesamte Anwendung nach wie vor wie geplant läuft.

Wer sich die Leistung des Caches gerne in Zahlen ansehen will, kann jetzt varnishstat laufen lassen und mitverfolgen, wie der Cache sich füllt und – hoffentlich – immer bessere Trefferquoten erzielt.

Es gibt noch viel zu tun: Cache-Tuning…

Insbesondere wer varnish mit WordPress verwendet, wird schnell feststellen, dass die Trefferquoten mies sind. Das Problem ist, dass WordPress im großen Stil Cookies verwendet. Einen Einstieg in das Thema bietet die Varnish-Community hier mit ihrer Seite „Varnish and WordPress“ (Vorsicht, die Seite ist über zwei Jahre alt… das geht bestimmt inzwischen noch besser. Unter anderem empfehle ich, den Cookie-Killer etwa so zu setzen: if (!((req.url ~ "(preview|wp-(login|admin))")|| [...], da dann auch die WordPress-Preview-Funktion am Leben bleibt).

Zur Verfeinerung der Konfiguration hier noch ein praktischer Trick: das Kommando sudo varnish_reload_vcl lädt die VCL-Dateien neu, ohne den Cache neu zu starten. (Soweit möglich verwendet varnish wohl auch bei einem Neustart die schon gecacheten Daten, aber wozu…)

Es gibt viel zu tun:

  • Encodings und Kompression optimieren
  • Webseiten-Namen normalisieren – bisher wird digitaler-heimwerker.de und www.digitaler-heimwerker.de getrennt gecached
  • HTTP-Header stutzen (z.B. Server und Via entfernen, um Hackern Hinweise zu nehmen
  • Falls nicht nur WordPress verwendet wird: Denn Cookie-Killer besser zielen (eine Nur-mit-Anmelden-Mediawiki-Instanz wurde bspw. durch den Cookie-Killer vorübergehend lahmgelegt)
  • und so weiter, und so weiter…