Direkt zum Inhalt

Drupal Caching mit Pressflow und Varnish

11.05.2010 - 19:00 von Gast

Es war mal wieder soweit, der Amazon EC2 Server von Rätsel-Contest und Krupion war auch mit den aktuell installierten Caching Systemen in Drupal und Boost an seine Grenzen gestoßen. Grund dafür ist natürlich der ständig zunehmende Load und das mitlerweile doch recht hohe Benutzeraufkommen. Da reichte das einfach Caching auf DB Basis nicht mehr aus. Auch wenn die Inhalte mit Boost statisch aus dem Dateisystem geliefert werden, wird dazu immer noch der Apache benötigt. Das erzeugt natürlich deutlich überflüssige Lasten. Sinnvoller wäre es doch, statische Files zu cachen und diese ohne Apache, z.B. über einen deutlich schnelleren Server auszuliefern, ohne dass der Apache aktiv werden muss. Die Lösung dafür schien mir Varnish als Referse-Proxy zu sein. Varnish in Kombination mit der Drupal-Distribution Pressflow schienen mir die perfekte Lösung. Da Pressflow 100% Kompatibel mit Drupal ist, konnte das laufende Portal einfach mit Varnish "überschrieben" werden. Und auch ohne Varnish zuvor installiert zu haben lief die Seite einfach weiter. Laut Pressflow sollte auch das schon deutlich die Performance verbessern, da diese Distribution für PHP5 und MySQL optimiert ist.

WICHTIG: Bevor Sie damit beginnen, sollten Sie sich bewusst sein, dass Sie alle Seiten über Varnish laufen lassen müssen, wenn Sie dieses auf dem Server installieren, da Varnish auf Port 80 listen muss und somit das Listen auf Port 80 des Apache nicht mehr möglich ist. Dieser Dient dann nur noch als Backend, dazu aber später mehr.

Nun aber zum Wesentlichen. Nachdem wir Drupal mit der aktuellen Pressflowinstallation geupdated haben fügen wir in die settings.php folgenden Code ein:

$conf = array(
  'reverse_proxy' => TRUE,
  'reverse_proxy_addresses' => array(
    '127.0.0.1', // Reverse proxy host A, es kann mehrere geben
  ),
);

Dann installieren wir Varnish auf unserem Debian Lenny Server.

apt-get install varnish

installiert uns die aktuelle Distribution. ACHTUNG: Sollten Sie eine alte Debian Etch Version einsetzen, sollten Sie Varnish manuell herunterladen und kompilieren, da diese sonst nicht aktuell ist.

Anschließend müssen zwei Dateien bearbeitet werden:

nano /etc/default/varnish

in dieser Datei habe ich lediglich folgenden Abschnitt eingestellt:

DAEMON_OPTS="-a :80 \
                -T localhost:6082 \
                -f /etc/varnish/default.vcl \
                -S /etc/varnish/secret \
                -p thread_pools=4 \
                -p thread_pool_max=1500 \
                -p listen_depth=2048 \
                -p lru_interval=1800 \
                -h classic,169313 \
                -p connect_timeout=600 \
                -p max_restarts=6 \
                -s malloc,1G"

Das bedeutet folgendes: varnish listened auf Port 80 (daher wird der Apache gleich noch auf einen anderen Port 8080 geleget), -T gibt den Port des Controling-Interfaces an, -S die Konfigurationsdatei (bearbeiten wir gleich noch), -p connect_timeout setzt das Timeout für Connections höher um 503 Errors zu vermeiden bei hoher Last.
Varnish kann den Cache im Dateisystem aufbauen oder im Speicher. Im Speicher ist natürlich deutlich schneller daher entscheiden wir uns für diese Variante. Wir wollen aber auch, dass sich Varnish nicht mit Speicher "totfrisst" und anderen Anwendungen kein RAM mehr zur Verfügung steht, oder es eine Endlos-SWAP-Schleife gibt die den Server in die Knie zwingt. Daher begrenzen wir den maximal zur Verfügung stehenden Speicher für Varnish auf 1GB mit -s malloc,1G

Nun bearbeiten wir die Datei

nano /etc/varnish/default.vcl

wir legen zunächst das Defauult Backend fest. Dorthin leitet Varnish die Anfragen weiter, wenn diese nicht durch den Cache beantwortet werden können. Das Backend kann natürlich auch auf einem anderen Server liegen, das ist bei uns aber (noch) nicht der Fall.

backend default {
     .host = "127.0.0.1";
     .port = "8080";  //Apache muss auf diesem Port Listen!
     .connect_timeout = 600s;
     .first_byte_timeout = 600s;
     .between_bytes_timeout = 600s;
 }

Nun definieren wir den Requesthandler:

sub vcl_recv {
 #has_js und Google Analytic entfernen
  set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|has_js)=[^;]*", "");

 #";" prefix entfernen wenn vorhanden
  set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");

 #Leere Cookies entfernen
       if (req.http.Cookie ~ "^\s*$") {
               unset req.http.Cookie;
       }

 #domainspezifische Einstellungen
  if (req.url ~ "^/sites/SITE1.de/*" || req.url ~ "^/sites/SITE2.de/*" || req.url ~ "^/sites/SEITE3.de/*" ) {
                        unset req.http.Cookie;
                }

 #Them JS und CSS von Drupal Cachen
  if (req.url ~ "^/modules/.*\.(js|css)\?") {
                        unset req.http.Cookie;
                }

  #beliebige weitere URLs explizit Cachen
                if (req.url ~ "^/BLA/BLUB/FOO*")
                {
                         unset req.http.Cookie;
                }

 #Andere URLs explizit NICHT CACHEN!
 #Pass Cronjobs and server-status
                if (req.url ~ "cron.php") {
                        return (pass);
                }
                if (req.url ~ ".*/server-status$") {
                        return (pass);
                }

}

sub vcl_hash { if (req.http.Cookie) { set req.hash += req.http.Cookie; } }

Das wars. Wie man sieht, lässt sich mit der Sprache VCL alles bis ins kleinste Detail steuern. Mit

return (pass);

lässt Varnish den Request zum Backend durch. Mit

unset req.http.Cookie;

wird gecached.

Das waren alle Einstellungen, die wir für eine Pressflow Drupal-Spezifische Varnish Konfiguration vornehmen müssen.

Nun loggen wir uns in Drupal als Admin ein und stellen den Cache passend ein. Pressflow bietet uns dazu eine neue Cacheoption an - ("Extern") - unter /admin/settings/performance. Wir setzen also den Radiobutton auf "Extern" und Drupal weiß, dass durch eine Reverseproxy gecached wird.

Sobald wir Varnish neu starten, versucht es auf Port 80 zu listen um die Browseranfragen noch vor dem Apache abzubekommen. Das macht Sinn. Allerdings darf der Apache nun nicht mehr auf Port 80 listen sondern, wie in unserem Beispiel, auf Port 8080.
Also legen wir die Ports all unserer vhosts auf 8080 und starten den Apache neu.

/etc/init.d/apache2 restart

Nun starten wir Varnish neu

/etc/init.d/varnish restart

und prüfen mit

ps ax | grep varnish

ob Varnish korrekt läuft. Sollte das nicht so sein, schauen wir in der /var/log/syslog nach, ob ein Fehler aufgetreten ist. Sollte das nicht der Fall sein, ist auch dort die erfolgreiche Startmeldung von Varnish zu sehen.

Nun sollte schon alles funktionieren. Ob es auch wiklich klappt, kann man entweder im Header der Browseranfrage (bzw. der Serverantwort "via Varnish") sehen oder mit folgenden Befehlen:

varnishtop -b -i TxURL 

zeigt alle Requests, die zum Backend durchgelassen wurden.

varnishhist 

zeigt ein Histogramm an, "|" bedeutet hit, also durch Varnish-Cache beantwortet, "#" bedeutet nicht gecached, also zum Drupal-Backend weitergeleitet.

Um nun auch noch die Backendanfragen deutlich performanter abarbeiten zu können, sollte man noch APC installieren.

Das geht auf eine Debian System mit

pecl install apc

Das war schon von Debian Seite aus. Damit APC verwendet wird, muss in der settings.php nun folgender Code ergänzt werden (nach der Ergänzung die ich oben beschrieben habe)

$conf['cache_inc'] = './sites/all/modules/authcache/authcache.inc'; //wenn man noch authcache verwendet
$conf['cacherouter'] = array(
  'default' => array(
    'engine' => 'apc',
    'server' => array(),
    'shared' => TRUE,
    'prefix' => 'DOMAIN-de',  //eigentlich nur wichtig bei Multisite installationen
    'path' => 'sites/default/files/filecache',  //wenn man Filecache statt RAM Cache verwenden wiill
    'static' => FALSE,
    'fast_cache' => TRUE,
  ),
 'cache_form' => array(
	'engine' => 'db',  //WICHTIG: sonst funktionieren die AJAX Formulare nicht bekannter Fehler "...coult not be found in form-cache..."
  ),
); 

Am besten nochmal den Apache neustarten (siehe oben) und schon sind wir fertig.

Das Ergebnis:

Deutlich bessere Performance (natürlich auch in Abhängigkeit der Cacheeinstellungen). Die Seiten werden nun locker mit 10 facher Geschwindigkeit ausgeliefert und der Server Load ist um das 10 Fache reduziert. Wie das geht? Ja, wir hatten teilweise Serverloads von über 30, das hat sich nun dank Varnish und Pressflow Drupal auf 1-3 eingependelt.

Die Seite ist so schnell, dass es uns sogar die User danken:

Die Seite ist spürbar schneller geworden. Super Arbeit!

Bei Fragen, gerne per Email oder über die Kommentarfunktion melden.

P.S. ich bin immer noch sehr begeistert über die neue Performance!

Registrieren Sie sich jetzt für unseren kostenlosen Newsletter und bleiben Sie immer auf dem Laufenden

Weitere Blogbeiträge