varnish & co
Florian Holzhauer - @fholzhauer
php unconference hamburg 2012
http://holzhauer.it
Disclaimer
 „Bauchentscheidungen“
   nicht totoptimiert
   Aufwand / Nutzen
 Es gibt meistens mehr als eine Lösung
   lighttpd, nginx, $webserver
   XCache, APC, eAccelerator
Überblick

Problem: LAMP-Maschine unter Last
varnish
  Standard-Administration
  fancy features
Optimierung für Faule: xCache, tuning-primer.sh
Beispiel: lawblog.de

 Kein „echtes“ Kundenprojekt, trotzdem viel Last
   Guter Kontakt, alle Adminfreiheiten
   Testbed für neue Tools
   Sehr gutes Besucher-Feedback
 Klassische L(A)MP-Anwendung: Wordpress, Lighttpd,
 MySQL, PHP.
lawblog.de: 2005

„Wahnsinn, 3.000 Besucher an einem Tag!“
..und dann kam Spiegel Online
  Load > 70, lokale Konsole tot
Apache 1.3, Wordpress 1.5, nichts optimiert
Schnapsidee: Blacklist

 Viele Bots, Crawler, komische Scripte
 wget -m http://www.lawblog.de/
   „Offline lesen“ (...)
 Idee: Automatisiert die Top-5-Traffic-erzeuger jeden
 Monat in die Blacklist.
Super Plan.




 b3091322.crawl.yahoo.net ist übrigens inzwischen seit Monaten Traffic-Platz 1..
lawblog.de: 2012

 busybox httpd/1.35 varnish 3 + lighttpd 1.4
 Eigener Server bei vollmar.net
Aktuelles Setup

 pound

 varnish   lighttpd   php-fpm

                       mysql
varnish
    Reverse Proxy
    „Squid is 1975 architecture, varnish 2006“
      http://varnish-cache.org/wiki/ArchitectNotes

„One varnish doing about 4320 million req/day,
 peaks at 8K reqs/s.

This particular varnishbox is a HP Proliant BL460c G1
2XDualcore 2.66 Ghz with 6 GB of RAM.
Running Centos5.3. Only tuning is /var/lib/varnish on tmpfs“

(Aus: varnish-misc Mailingliste)
varnish: Features

 VCL - Configlanguage
 Loadbalancing with health checking of backends
 Partial ESI support
 URL rewriting
 Graceful handling of dead backends
Varnish: Konzept
Varnish: VCL
sub vcl_fetch {
    if (req.url ~ "^/index.php/archives/200") {
        set beresp.http.Cache-Control = "max-age=1000";
        set beresp.ttl = 600s;
        unset beresp.http.set-cookie;
        return (deliver);
      }
      if (req.url ~ "^/$") {
        set beresp.http.Cache-Control = "max-age=30";
        set beresp.ttl = 15s;
        unset beresp.http.set-cookie;
        return (deliver);
    }
    if (req.url ~ ".(png|gif|jpg|swf|css|js)$") {
        set beresp.http.Cache-Control = "max-age=14400";
        set beresp.ttl = 1w;
        unset beresp.http.set-cookie;
        return (deliver);
    }
Varnish: VCL

TTL für die jeweilige Seite anpassen
Alter Content darf länger in den Cache
Grafiken: welche ändern sich oft, welche nie?
vcl_hash: „Was ist der selbe Request“
Varnish: VCL

    In VCL programs, C program code can be put
    anywhere, simply by enclosing it in C{ ... }C
sub vcl_fetch {
    if (req.url ~ "^/something-special") {
       C{
! ! syslog(LOG_ERR, "Spurious response from backend: xid %s request %s %s
"%s" %d "%s" "%s"", VRT_r_req_xid(sp), VRT_r_req_request(sp),
VRT_GetHdr(sp, HDR_REQ, "005host:"), VRT_r_req_url(sp),
VRT_r_obj_status(sp), VRT_r_obj_response(sp), VRT_GetHdr(sp, HDR_OBJ,
"011Location:"));
! }C
     }
Varnish: ESI
     Seitenteile getrennt cachen
        z.B. „Widgets“
        nicht alle ESI Features
index.html:
<HTML><BODY>
The time is: <esi:include src="/cgi-bin/date.cgi"/> at this very moment.
</BODY></HTML>

config:
sub vcl_fetch {
    if (req.url == "/index.html") {
        esi; /* Do ESI processing */
        set obj.ttl = 24 h;
    } elseif (req.url == "/cgi-bin/date.cgi") {
        set obj.ttl = 1m;
    }
}
Varnish: Load balancing

Health Polling
  Kaputtes Backend = „auslassen“
Backendwahl: Random, Round-Robin
  ..oder via VCL
Varnish: Backend tricks

 Neuen Content abholen während alter noch
 ausgeliefert wird
 Defektes Backend: Interne TTL hochdrehen („grace“)
 Gestaltbare Fehlermeldung
   „Der Webserver wird einer Wartung unterzogen.
   Etwas Geduld.“
Varnish: Purge

Content explizit invalidieren
Über Telnet-Schnittstelle oder Console-Tool
  Auch Wildcards
Optional: HTTP Purge Requests
  Das Webscript kann selbst Updates triggern
Varnish: Tut nicht

 HTTPS
 Cookies
 „eigene“ Content-Modifikationen
 Logfiles
Varnish: HTTPS

varnish spricht nur plain http
„Fix“: Pound oder Stunnel davor
Problem: $_SERVER[„HTTPS“];
Problem: $_SERVER[„REMOTE_ADDR“];
Variablen-Workaround
auto_prepend_file = /var/www/prepend.php
<?php
if(array_key_exists('HTTP_X_FORWARDED_PROTO',$_SERVER)){
  if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
    $_SERVER['HTTPS']='on';
  }else{
    $_SERVER['HTTPS']='';
  }
}
if (array_key_exists('HTTP_X_FORWARDED_FOR',$_SERVER)) {
  $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
} else if (array_key_exists("HTTP_CLIENT_IP",$_SERVER)) {
  $ip = $_SERVER["HTTP_CLIENT_IP"];
} else {
  $ip = $_SERVER["REMOTE_ADDR"];
}
$_SERVER['REMOTE_ADDR'] = $ip;
Varnish: Cookies


Philosophie: „nur nicht personalisierte Seiten cachen“
Workaround: unset beresp.http.set-cookie;
Varnish: Content
Modifikationen

Varnish „interessiert“ Seiten-Content nie
  ausser ESI
Nur Header-Modifikationen
  in beide Richtungen
Varnish: logfiles

 Varnish hat sehr gute Debuggingtools
   aber: Log nur in shared memory, wird nicht
   geschrieben
 „Fix“: varnishncsa
   Liest shared memory, schreibt nach Apache-format-
   Log
Varnish: Tools
 varnishhist
   Geschwindigkeits-Histogramm
 varnishstat
   „top“ für varnish
 varnishlog
   zeigt/filtert shared memory log
varnish: Quick‘n dirty
 Webserver von Port 80 wegziehen
 vi /etc/default/varnish
   varnish auf Port 80
 vi /etc/varnish/default.vcl
   backend anpassen: Webserver-IP und -Port
 Starten, fertig.
Wiggly lines
 Was bringt varnish eigentlich?

                   komplett aus




 nur / und feeds                  komplett an
Wiggly lines II
Genug varnish.

 pound

 varnish   lighttpd   php-fpm

                       mysql
pound

Kann Loadbalancing
 mit Session Handling
 Kann bis auf caching viel was varnish auch kann
 HTTP Sanitizing
Bei mir: Reiner HTTPS->HTTP Wrapper
XCache: Opcode
 PHP Opcode Caching
 Unbedingt Default-Config „aufbohren“
 Web-Interface hilft
XCache: varcache
Kann auch varcache
„memcached für arme“
  Weniger Features, aber dafür ein Daemon weniger
Obskure Race-Conditions bei Wordpress


-> apc
MySQL „Tuning“
Halbe „Wissenschaft“
Gute Literatur
Aber: Oft reicht auch die faule Variante
  ..und ich bin gern faul :-)
http://www.day32.com/MySQL/
  tuning_primer.sh
tuning_primer.sh
 Braucht „bc“
 MySQLd sollte mindestens 24 Stunden laufen
 sh ./tuning_primer.sh
   „Übersetzt“ MySQL-Status-Variablen
   Read-Only
 Nicht einfach blind übernehmen
tuning_primer.sh
Caching
„Your mileage may vary“
  Caching massiv Anwendungsspezifisch
Blind überall cachen bringt Ärger
  Race Conditions
  Redundante Datenhaltung
  Cache purging?
Caching

Besser: Bottlenecks finden
  PHP Profiling
  Benchmarks
Ideal: Applikation braucht gar keinen Cache
Danke :-)

 Fragen?
 http://www.varnish-cache.org
 http://www.apsis.ch/pound/


 https://gist.github.com/3378020
Varnish PHP Unconference Hamburg 2012

Varnish PHP Unconference Hamburg 2012

  • 1.
    varnish & co FlorianHolzhauer - @fholzhauer php unconference hamburg 2012 http://holzhauer.it
  • 2.
    Disclaimer „Bauchentscheidungen“ nicht totoptimiert Aufwand / Nutzen Es gibt meistens mehr als eine Lösung lighttpd, nginx, $webserver XCache, APC, eAccelerator
  • 3.
    Überblick Problem: LAMP-Maschine unterLast varnish Standard-Administration fancy features Optimierung für Faule: xCache, tuning-primer.sh
  • 4.
    Beispiel: lawblog.de Kein„echtes“ Kundenprojekt, trotzdem viel Last Guter Kontakt, alle Adminfreiheiten Testbed für neue Tools Sehr gutes Besucher-Feedback Klassische L(A)MP-Anwendung: Wordpress, Lighttpd, MySQL, PHP.
  • 5.
    lawblog.de: 2005 „Wahnsinn, 3.000Besucher an einem Tag!“ ..und dann kam Spiegel Online Load > 70, lokale Konsole tot Apache 1.3, Wordpress 1.5, nichts optimiert
  • 6.
    Schnapsidee: Blacklist VieleBots, Crawler, komische Scripte wget -m http://www.lawblog.de/ „Offline lesen“ (...) Idee: Automatisiert die Top-5-Traffic-erzeuger jeden Monat in die Blacklist.
  • 7.
    Super Plan. b3091322.crawl.yahoo.netist übrigens inzwischen seit Monaten Traffic-Platz 1..
  • 8.
    lawblog.de: 2012 busyboxhttpd/1.35 varnish 3 + lighttpd 1.4 Eigener Server bei vollmar.net
  • 9.
    Aktuelles Setup pound varnish lighttpd php-fpm mysql
  • 10.
    varnish Reverse Proxy „Squid is 1975 architecture, varnish 2006“ http://varnish-cache.org/wiki/ArchitectNotes „One varnish doing about 4320 million req/day, peaks at 8K reqs/s. This particular varnishbox is a HP Proliant BL460c G1 2XDualcore 2.66 Ghz with 6 GB of RAM. Running Centos5.3. Only tuning is /var/lib/varnish on tmpfs“ (Aus: varnish-misc Mailingliste)
  • 11.
    varnish: Features VCL- Configlanguage Loadbalancing with health checking of backends Partial ESI support URL rewriting Graceful handling of dead backends
  • 12.
  • 13.
    Varnish: VCL sub vcl_fetch{ if (req.url ~ "^/index.php/archives/200") { set beresp.http.Cache-Control = "max-age=1000"; set beresp.ttl = 600s; unset beresp.http.set-cookie; return (deliver); } if (req.url ~ "^/$") { set beresp.http.Cache-Control = "max-age=30"; set beresp.ttl = 15s; unset beresp.http.set-cookie; return (deliver); } if (req.url ~ ".(png|gif|jpg|swf|css|js)$") { set beresp.http.Cache-Control = "max-age=14400"; set beresp.ttl = 1w; unset beresp.http.set-cookie; return (deliver); }
  • 14.
    Varnish: VCL TTL fürdie jeweilige Seite anpassen Alter Content darf länger in den Cache Grafiken: welche ändern sich oft, welche nie? vcl_hash: „Was ist der selbe Request“
  • 15.
    Varnish: VCL In VCL programs, C program code can be put anywhere, simply by enclosing it in C{ ... }C sub vcl_fetch { if (req.url ~ "^/something-special") { C{ ! ! syslog(LOG_ERR, "Spurious response from backend: xid %s request %s %s "%s" %d "%s" "%s"", VRT_r_req_xid(sp), VRT_r_req_request(sp), VRT_GetHdr(sp, HDR_REQ, "005host:"), VRT_r_req_url(sp), VRT_r_obj_status(sp), VRT_r_obj_response(sp), VRT_GetHdr(sp, HDR_OBJ, "011Location:")); ! }C }
  • 16.
    Varnish: ESI Seitenteile getrennt cachen z.B. „Widgets“ nicht alle ESI Features index.html: <HTML><BODY> The time is: <esi:include src="/cgi-bin/date.cgi"/> at this very moment. </BODY></HTML> config: sub vcl_fetch { if (req.url == "/index.html") { esi; /* Do ESI processing */ set obj.ttl = 24 h; } elseif (req.url == "/cgi-bin/date.cgi") { set obj.ttl = 1m; } }
  • 17.
    Varnish: Load balancing HealthPolling Kaputtes Backend = „auslassen“ Backendwahl: Random, Round-Robin ..oder via VCL
  • 18.
    Varnish: Backend tricks Neuen Content abholen während alter noch ausgeliefert wird Defektes Backend: Interne TTL hochdrehen („grace“) Gestaltbare Fehlermeldung „Der Webserver wird einer Wartung unterzogen. Etwas Geduld.“
  • 19.
    Varnish: Purge Content explizitinvalidieren Über Telnet-Schnittstelle oder Console-Tool Auch Wildcards Optional: HTTP Purge Requests Das Webscript kann selbst Updates triggern
  • 20.
    Varnish: Tut nicht HTTPS Cookies „eigene“ Content-Modifikationen Logfiles
  • 21.
    Varnish: HTTPS varnish sprichtnur plain http „Fix“: Pound oder Stunnel davor Problem: $_SERVER[„HTTPS“]; Problem: $_SERVER[„REMOTE_ADDR“];
  • 22.
    Variablen-Workaround auto_prepend_file = /var/www/prepend.php <?php if(array_key_exists('HTTP_X_FORWARDED_PROTO',$_SERVER)){ if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') { $_SERVER['HTTPS']='on'; }else{ $_SERVER['HTTPS']=''; } } if (array_key_exists('HTTP_X_FORWARDED_FOR',$_SERVER)) { $ip = $_SERVER["HTTP_X_FORWARDED_FOR"]; } else if (array_key_exists("HTTP_CLIENT_IP",$_SERVER)) { $ip = $_SERVER["HTTP_CLIENT_IP"]; } else { $ip = $_SERVER["REMOTE_ADDR"]; } $_SERVER['REMOTE_ADDR'] = $ip;
  • 23.
    Varnish: Cookies Philosophie: „nurnicht personalisierte Seiten cachen“ Workaround: unset beresp.http.set-cookie;
  • 24.
    Varnish: Content Modifikationen Varnish „interessiert“Seiten-Content nie ausser ESI Nur Header-Modifikationen in beide Richtungen
  • 25.
    Varnish: logfiles Varnishhat sehr gute Debuggingtools aber: Log nur in shared memory, wird nicht geschrieben „Fix“: varnishncsa Liest shared memory, schreibt nach Apache-format- Log
  • 26.
    Varnish: Tools varnishhist Geschwindigkeits-Histogramm varnishstat „top“ für varnish varnishlog zeigt/filtert shared memory log
  • 27.
    varnish: Quick‘n dirty Webserver von Port 80 wegziehen vi /etc/default/varnish varnish auf Port 80 vi /etc/varnish/default.vcl backend anpassen: Webserver-IP und -Port Starten, fertig.
  • 28.
    Wiggly lines Wasbringt varnish eigentlich? komplett aus nur / und feeds komplett an
  • 29.
  • 30.
    Genug varnish. pound varnish lighttpd php-fpm mysql
  • 31.
    pound Kann Loadbalancing mitSession Handling Kann bis auf caching viel was varnish auch kann HTTP Sanitizing Bei mir: Reiner HTTPS->HTTP Wrapper
  • 32.
    XCache: Opcode PHPOpcode Caching Unbedingt Default-Config „aufbohren“ Web-Interface hilft
  • 33.
    XCache: varcache Kann auchvarcache „memcached für arme“ Weniger Features, aber dafür ein Daemon weniger Obskure Race-Conditions bei Wordpress -> apc
  • 34.
    MySQL „Tuning“ Halbe „Wissenschaft“ GuteLiteratur Aber: Oft reicht auch die faule Variante ..und ich bin gern faul :-) http://www.day32.com/MySQL/ tuning_primer.sh
  • 35.
    tuning_primer.sh Braucht „bc“ MySQLd sollte mindestens 24 Stunden laufen sh ./tuning_primer.sh „Übersetzt“ MySQL-Status-Variablen Read-Only Nicht einfach blind übernehmen
  • 36.
  • 37.
    Caching „Your mileage mayvary“ Caching massiv Anwendungsspezifisch Blind überall cachen bringt Ärger Race Conditions Redundante Datenhaltung Cache purging?
  • 38.
    Caching Besser: Bottlenecks finden PHP Profiling Benchmarks Ideal: Applikation braucht gar keinen Cache
  • 39.
    Danke :-) Fragen? http://www.varnish-cache.org http://www.apsis.ch/pound/ https://gist.github.com/3378020