Samstag, den 12. Mai 2012 17:24 Alter: 5 Monat(e)
Kategorie: Tuning
Submitting your vote...
Rating: 5.0 von 5. 3 Stimme(n).
Artikel bewerten.

Optimierte Varnish3 Konfiguration für TYPO3

Der statische Content einer Webseite sollte nicht bei jedem Aufruf durch ein CMS gerendert werden. Nach einigen Optimierungen lässt sich nahezu jeder Seitenaufruf einer TYPO3 serverseitig durch den Varnish-Cache beschleunigen.


TYPO3 Seite hinter Varnish-Cache

TYPO3 Seite hinter Varnish-Cache

Die grenzen des Caches von TYPO3

Obwohl TYPO3 über sehr ausgefeilte Techniken verfügt, um unveränderte Inhalte nicht unveränderte Inhalte nicht bei jedem Aufruf komplett neu zu berechnen, ist es sinnvoll das Caching serverseitig zu unterstützen. Denn auch eine intern gecachte Seite muss noch aus der Datenbank geholt werden und durch den PHP-Interpreter wandern.
Um das zu verdeutlichen habe ich den zweimaligen Aufruf einer TYPO3-Webseite mit xdebug protokolliert.
Beim ersten Aufruf der Startseite einer ziemlich umfangreichen TYPO3-Seite listet der Funktions-Trace 20844 Funktionsaufrufe. Beim zweiten Aufruf, also nachdem TYPO3 die Seite cachen konnte, sind es immerhin noch 9038.

Die Verarbeitung dieser Funktionen durch den PHP-Interpreter und die Abarbeitung im Prozessor kosten Zeit, CPU-Ressourcen und RAM. Wer das ausprobieren möchte kann ja mal einen Benchmark wie siege oder den AB-Benchmark mit 20 oder 30 gleichzeitigen Anfragen auf eine TYPO3-Webseite ohne statischen Cache loslassen und gleichzeitig den RAM-Verbrauch des Servers beobachten.

Statischer Cache

Um statische Inhalte schon serverseitig zu cachen gibt es mehrere Möglichkeiten. Erweiterungen von TYPO3 wie nc_staticfilecache generieren html-Dateien und nutzen das Rewrite-Modul des Webserver um statt der index.php von TYPO3 die so zwischengespeicherten Daten aufzurufen.

Noch flexibler ist es vor den Webserver einen Caching-Reverse-Proxy wie den Varnish-Cache zu schalten. Damit der mit TYPO3 effektiv zusammenarbeitet ist noch etwas Konfigurationsarbeit notwendig.

Varnish für TYPO3 optimieren

Unnötige Cookies löschen

Nach der Einrichtung des Cachingproxies dürften die meisten erst mal über das Ergebnis enttäuscht sein. Weder die Last auf dem Server, noch die Auslieferungsgeschwindigkeit dürfte bei den meisten Webseiten zunehmen. Der Grund ist, dass TYPO3 standardmäßig im Frontend ein Cookie setzt. Durch dieses individuelle Cookie, ist aus Sicht das Caches jede Seite ein Einzelstück und muss individuell vom Webserver angefragt werden.

Eine Möglichkeit das Verhalten abzuschalten, ist in der localconf.php von TYPO3 die Zeile

  1. $TYPO3_CONF_VARS['FE']['dontSetCookie'] = 1


einzufügen.

Da TYPO3 leider von Haus aus nicht in der Lage ist cookies nur dort zu setzten wo es auch sinnvoll und notwendig wäre, führt die obige Einstellung dazu, dass Erweiterungen die ein Cookie erwarten nicht mehr funktionieren.

Die Erweiterung MOC Varnish erlaubt laut changelog seit der Version 1.2 zu entscheiden wo ein Cookie gesetzt wird. In der Dokumentation habe ich jedoch keine Details dazu gefunden.

Cookies können aber auch sehr einfach im Varnish selbst gelöscht werden. So ist möglich anhand der URL zu entscheiden, evtl. doch Cookies zu erlauben.

Die Zeile

  1. unset req.http.Cookie;

kann innerhalb beliebiger IF-Abfragen erfolgen.

Cache löschen (purging bzw, baning)

Die schon erwähnte Erweiterung MOC_varnish stellt eine Möglichkeit beriet den Cache des Varnish zu löschen, wenn auch der Cache von TYPO3 geleert wird.
Da ich nur Erweiterungen installieren möchte, die ich unbedingt brauche um möglichst wenig Fehlerquellen und unnötigen PHP-Code auf dem System zu haben, habe ich mich für eine andere Lösung entscheiden.

Die Zeilen

  1. if (req.http.cookie ~ "be_typo_user"){
  2.   ##Inhalten löschen wenn Shift+reload gedrückt wird,
  3.   ##aber nur bei eingeloggtem user (Backend-Cookie)
  4.   if (req.http.Cache-Control ~ "no-cache") {
  5.                 set req.ttl = 0s;
  6.                 ban("req.url == " + req.url);
  7.                 return (pass);
  8.             }
  9. }


sorgen dafür, dass eine einzelne Unterseite aus dem Cache gelöscht wird, sobald ein im Backend eingeloggter User das Frontend besucht und dort im Browser shift+reload drückt.

Da ich nach Änderungen mir diese eh im Frontend ansehe, ist das eine für mich sehr praktikable Lösung.

Auf die in vielen Beispielen zum Varnish zu findende Möglichkeit direkt über  


  1. if (req.http.Cache-Control ~ "no-cache") {
  2.     return (pass);
  3. }


jedem Client die Möglichkeit zu geben die Seite ohne Cache ausgeliefert zu bekommen habe ich verzichtet. Jemand der gezielt den Cache umgehen möchte um z.B. den Server lahm zu legen kann zwar bei der obigen Lösung auch das TYPO3-Cookie fälschen oder POST-Anfragen stellen. Das muss ein Angreifer aber erst einmal herausfinden. Außerdem möchte ich sicherstellen, dass Bots von Suchmaschinen, welche die Seiten parsen diese in der besten Geschwindigkeit ausgeliefert bekommen, egal mit welchem header sie kommen.

Cache nach Kommentaren aktualisieren

Auf dieser Seite ist es möglich Kommentare zu den Artikeln zu verfassen. Die Kommentare werden derzeit ohne Kontrolle direkt online gestellt. Nach einem neuen Kommentar ist es nötig, dass der Cache neu aufgebaut wird.

Um das zu gewährleisten erlaube ich den Cache zu löschen, wenn eine Anfrage per Post auf den Server antrifft. In der Varnish-Konfiguration erledigen das die Zeilen:

  1. if (req.request == "POST") {
  2.         ban("req.url == " + req.url);
  3.         set req.http.X-Test = req.url;
  4.         return (pass);
  5.  }


Ergebnis

Wenn eine Webseite vollständig vom Varnish gecacht wird, dürfte in den meisten Fällen die Bandbreite und Latenz der Anbindung die Grenze für die Auslieferungsgeschwindigkeit und die Serverauslastung darstellen. Die obige Grafik aus dem ab-Benchmark zeigt das recht eindrucksvoll.

Ein kleines Bash-Script, welches auf der Downloadseite bereit steht zeigt auch sehr eindrucksvoll den Geschwindigkeitsgewinn durch den Cache.

Mit Hilfe von wget lädt das Script rekursiv alle Unterseiten einer Domain. Die Zeit, welche zum Aufrufen aller Seiten benötigt wird hält es in einem Logfile fest.

Lokal aufgerufen ist das Ergebnis  für typo3.lygie.de:

Ohne Cache:

  1. Beginn: Sa 12. Mai 13:08:07 CEST 2012
  2. Ende: Sa 12. Mai 13:08:09 CEST 2012
  3. Laufzeit:  2.091133501


Mit Cache:
  1. Beginn: Sa 12. Mai 13:08:18 CEST 2012
  2. Ende: Sa 12. Mai 13:08:19 CEST 2012
  3. Laufzeit:  .173116479


Mit Cache sind die Aufrufe also ca. um den Faktor 12 schneller.

Hier noch die vollständige Varnish-Configuration

  1. backend nginx {
  2.     .host = "127.0.0.1";
  3.     .port = "8080";
  4. }
  5.  
  6. sub vcl_recv {
  7.     if (req.http.x-forwarded-for) {
  8.         set req.http.X-Forwarded-For =
  9.         req.http.X-Forwarded-For + ", " + client.ip;
  10.     } else {
  11.         set req.http.X-Forwarded-For = client.ip;
  12.     }
  13.  
  14.     set req.backend = nginx;
  15.  
  16.     if (req.request == "POST") {
  17.         ban("req.url == " + req.url);
  18.         set req.http.X-Test = req.url;
  19.         return (pass);
  20.     }
  21.  
  22.  
  23.     if (req.request != "GET" &&
  24.         req.request != "HEAD" &&
  25.         req.request != "PUT" &&
  26.         req.request != "POST" &&
  27.         req.request != "TRACE" &&
  28.         req.request != "OPTIONS" &&
  29.         req.request != "DELETE") {
  30.         return (pipe);
  31.     }
  32.     if (req.request != "GET" && req.request != "HEAD") {
  33.         return (pass);
  34.     }
  35.     if (req.http.Authorization || req.http.Cookie) {
  36.         return (pass);
  37.     }
  38.     if(req.http.host ~ "typo3.lygie.de"){
  39.         ##TYPO3-Backend nicht cachen
  40.         if (req.http.cookie ~ "be_typo_user"){
  41.             ##Inhalten löschen wenn Shift+reload gedrückt wird,
  42.             ##aber nur bei eingeloggtem user (Backend-Cookie)
  43.             if (req.http.Cache-Control ~ "no-cache") {
  44.                 set req.ttl = 0s;
  45.                 ban("req.url == " + req.url);
  46.                 return (pass);
  47.             }
  48.         }
  49.         else{
  50.             ##Cookies von TYPO3-Seiten löschen
  51.             unset req.http.Cookie;
  52.  
  53.         }
  54.     }
  55.     return (lookup);
  56. }
  57.  
  58. sub vcl_fetch {
  59.     set beresp.ttl = 12h;
  60.     set req.grace = 24h;
  61.     if (req.url ~ "\.(jpeg|jpg|png|gif|ico|swf|js|css|txt|gz|zip|html)$") {
  62.             set beresp.ttl = 48h;
  63.     }
  64.     if(req.http.host ~ "typo3.lygie.de"){
  65.         if (beresp.http.set-cookie ~ "be_typo_user"){
  66.         }
  67.         else{
  68.             unset beresp.http.set-cookie;
  69.         }
  70.     }
  71.     return (deliver);
  72. }


Den kompletten code gibt es auch zum download.


keine Kommentare
Kommentar schreiben

* Bitte ausfüllen

*

*