NRW:Arbeitsgruppe/Technik/Varnish

Aus Piratenwiki
Wechseln zu: Navigation, Suche
ACHTUNG: Die Informationen hier im Wiki sind momentan nicht vollständig aktualisiert.
AG Technik NRW
Verwaltung: Übersicht | Protokolle | Dokumentation | FAQ
Dienste: E-Mail | Lists | Webcache | Blogs | Wikimirror | Domains | RT | Mumble | LAN | Serverstatus


Zur LTW2012 NRW suchen wir noch Hilfe! Bitte hier entlang!

Kurzer Exkurs: Warum cachen?

Ein HTTP-Request für eine heute übliche Webseite ist auf Serverseite teuer. Da müssen viele Dateien geöffnet werden, mehrere Datenbankabfragen gemacht werden, Inhalte zusammengebaut werden, usw. Und das für jede Anfrage erneut. Auch wenn sich gar nix geändert hat. Daher ist es sinnvoll die Antworten des Servers zwischenzuspeichern und diese Kopie auszuliefern. IdR ist es absolut ausreichend, wenn man dem User eine Webseite ausliefert, die bis zu 5 Minuten alt ist. So brandaktuell sind wenige Seiten, dass sie in "Echtzeit" laufen müssen.

Caching funktioniert dann besonders gut, wenn viele Clients das selbe haben wollen. Z.B. wenn auf WDR ein Werbesport von uns läuft und eine URL bewirbt, werden viele Leute in der nächsten halben Stunde diese URL ansurfen. Wenn der Webserver die Anfragen alle alleine beantworten muss, stirbt er den Heldentod. Wenn aber ein Cache davor steht, liefert der die 10.000 Anfragen aus dem RAM aus, und der Webserver wird in der halben Stunde nur 7 mal belästigt (Bei einer Cachezeit von 5 Minuten)!

Einen Nachteil von Caches will ich nicht verschweigen. Die Webserverlogs spiegeln nicht mehr die Realität wieder. Der Webserver sieht ja nur noch einen Bruchteil der Anfragen. Da wir aber eh sparsam loggen werden und uns ja sicher in erster Linie Statistiken interessieren, ist das Problem nicht besonders groß. Statistiken kann man auch aus dem Cache ziehen. Zur Not kann man noch auf ein Zählpixel o.ä. zurückgreifen, dass nie gecached wird so dass man zumindest einen Request pro Pageview im Webserverlog hat.

Ich glaube nicht, dass es sinnvoll oder nötig ist einen verteilten Cache auf bereitgestellten Root-Servern zu betreiben. Das macht sicher mehr Probleme als es nützt. Da ist es sinnvoller statt der Server etwas Geld zu sammeln um mehr RAM zu kaufen.

Fragen

  • Welche Probleme hat man konkret, wenn man mehr als einen Proxycache betreibt?

Wenn man die selber betreibt ist das kein großes Problem. Aber wenn man 5 Maschinen, mit unterschiedlichster Ausstattung und unterschiedlicher Qualität der Administration mit 5 verschiedenen Admins hat, dann ist das ganze doch deutlich Problembehafteter.

  • Wieso betrifft uns stale-if nicht?

Stale-If-Error wäre die bequeme Heilung gegen ILSE, also die Error 500 Probleme des Bundeswikis. Wobei ich da der Meinung bin, der Server ist falsch konfiguriert, die dürften gar nicht erst entstehen (der Server sollte so enge Limits haben, dass er keine Requests annimmt, die er nicht abarbeiten kann). Stale-if-backend_gone ist etwas, dass wir durchaus haben wollen und auch können ;)

  • In wie weit wird die Datenbank bei Caching belastet? Pro Website sind durchaus dynamische DB Abfragen möglich, je nach dem was der Benutzer so treibt

Entweder kommt die ganze Seite aus dem Cache oder aus dem Apachen (inkl. DB Abfragen). Sprich entweder werden Apache und DB belastet oder keiner ;) Ausschließlich statischer Content wie Bilder, etc. kann man komplett cachen. Und ja, man kann Webseiten so bauen, dass sie nicht cachebar sind. Sollten wir aber nicht machen. Man kann es echt übertreiben mit dem dynamischen Content. Was man nicht/kaum cachen kann: Alles wofür man üblicherweise Sessions und/oder Cookies nutzt (eingeloggte User, etc.) Seiten die sich bei jedem Aufruf ändern (man malt z.B. sinnloserweise die aktuelle Uhrzeit mit in die Seite).

  • Welche Cache "Tiefe" würdest du vorschlagen? Nur die Landingpage oder mehr Content?

Soviel wie möglich. Das System muss Werbespot-Peaks überstehen.

  • Wie sieht es mit interaktiven Inhalten aus, Kommentarfunktionen usw?

Das Schreiben ist natürlich nicht cachebar. Aber ist eine Kommentarfunktion defekt, wenn sie ein paar Minuten hinterherhinkt? Ich denke damit könnte man leben, bzw. für solch interaktiven Teile der Site, auch kürzere Cachezeiten nehmen.

  • Ist es deiner Meinung nach Sinnvoll, wenn wir einen Cache in einem anderen RZ betreiben? Je nach dem wie viele Anfragen da kommen, möglicherweise haben wir nur einen 100MBps Port.

Nein, ich glaube das ist nicht sinnvoll. 100MBit sind verdammt viel. Das mit Web-Traffiv vollzumachen schaffen wir mit 2 Server nur, wenn wir wenige, große, statische Dateien ausliefern.

  • Wollen wir den "dicken" Server wirklich idle laufen lassen? Wie sieht es mit Sockets aus?

Der ist nicht idle... Der wird mit dem Generieren des Contents genug zu tun haben.

Varnish

Varnish ist ein extrem leistungsfähiger Reverse-Proxy aka Webcache, der ausschließlich im RAM arbeiten kann, sich jedoch bei der Ressourcenverteilung im Gegesatz zu anderen Proxies auf das Betriebssystem verlässt. Dadurch fällt sehr viel Overhead der durch die Verwaltung der Speicherorte anfällt weg.

Konfiguration

/etc/default/varnish (Debian)

Hier werden diverse globale Einstellungen definiert, die nicht den eigentlichen Cache betreffen sondern den Varnish Prozess. In diesem Beispiel soll ausschließlich der Arbeitsspeicher für den Cache genutzt werden. Die Standardkonfiguration sieht eine Nutzung der Festplatte als Cache Ort vor.

NFILES=131072
MEMLOCK=82000
INSTANCE=$(uname -n)
VARNISH_VCL_CONF=/etc/varnish/default.vcl
VARNISH_LISTEN_ADDRESS=93.190.95.241
VARNISH_LISTEN_PORT=80
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
VARNISH_ADMIN_LISTEN_PORT=6082
VARNISH_TTL=120
DAEMON_OPTS="   -a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \
                -f ${VARNISH_VCL_CONF} \
                -T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \
                -t ${VARNISH_TTL} \
                -p thread_pools=4 \
                -p thread_pool_min=10 \
                -p thread_pool_max=5000 \
                -p thread_pool_add_delay=2 \
                -p cli_timeout=25 \
                -p lru_interval=10 \
                -s malloc,2G"
  • NFILES: Maximale Anzahl an Dateideskriptoren ("open files")
  • MEMLOCK: Maximale Größe des gelockten shared memory
  • INSTANCE: Name der Instanz, wird im Monitoring angezeigt
  • VARNISH_VCL_CONF: Der Pfad zur Varnish Cache Konfiguration
  • VARNISH_LISTEN_ADDRESS: Die Adresse auf der Varnish lauschen soll
  • VARNISH_LISTEN_PORT: Und der entsprechende Port
  • VARNISH_ADMIN_LISTEN_ADDRESS: Die Adresse auf der die Adminconsole lauschen soll
  • VARNISH_ADMIN_LISTEN_PORT: Und der entsprechende Port
  • VARNISH_TTL: Standard Timeout in Sekunden für den Cache falls das Backend oder die VCL keins angibt
  • thread_pools: Ein Thread Pool pro CPU Kern ist die grobe Richtlinie
  • thread_pool_min: Es werden mindestens 10 worker threads pro thread pool auf Vorrat gestartet
  • thread_pool_max: Pro Thread Pool dürfen maximal 5000 worker threads gestartet werden
  • thread_pool_add_delay: Um zu verhindern, dass der Kernel gegrillt wird, werden neue Threads im Abstand von mindestens 2ms geforkt.
  • cli_timeout: Timeout in Sekunden für die Adminconsole
  • lru_interval: Interval in Sekunden, in dem die "Least recently used" Liste aktualisiert wird
  • -s malloc: In diesem Fall wollen wir ausschließlich den Arbeitsspeicher (malloc) nutzen, daher werden 2GB Arbeitsspeicher als Speicherort definiert.

/etc/varnish/default.vcl

Die Konfiguration des Cache passiert über VCL (Varnish Configuration Language). Dadurch wird die Konfiguration sehr flexibel, man kann sogar inline-C benutzen. In der einfachsten Konfiguration reicht Varnish einfach alle Anfragen an das Backend weiter, das ist natürlich nicht Sinn der Sache. In diesem Beispiel läuft ein Apache HTTPD auf dem gleichen System, jedoch nicht auf dem externen Interface.

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

Weitere, anwendungsspezifische Konfigurationen, finden sich im Netz.

Links

Client IP am Backend

Durch den Cache wird die IP Adresse des anfragenden Clients nicht an das Backend weitergeleitet. Stattdessen sieht man nur die IP des Proxy-caches. Aus unterschiedlichen Gründen ist es sinnvoll, zu wissen wer eine Anfrage an das Backend macht. Zum einen um Fehler an der Konfiguration zu erkennen wenn Seiten nicht gecached werden, und zum anderne um potentielle Angriffe zu erkennen. So kann ein Client beispielsweise durch gezieltes Abfragen von nicht existierenden Seiten das Backend unter Last setzen da die entsprechenden Seiten nicht im Cache sind.

Abhilfe schafft hier mod_rpaf für Apache. RPAF (reverse proxy add forward module) sucht in HTTP Anfragen nach einem X-Forwarded-For Header und ersetzt die Ursprungsadresse durch dessen Wert.

Varnish muss dann nur noch dieses Headerfeld mit der Adresse des Clients ersetzen und schon kennt man seine Adresse am Backend.

sub vcl_recv {
        remove req.http.X-Forwarded-For;
        set req.http.X-Forwarded-For = client.ip;
}

mod_rpaf muss nun wissen, für welche Frontends die entsprechenden Header geändert werden müssen:

<IfModule mod_rpaf.c>
  RPAFenable On
  RPAFsethostname On
  RPAFproxy_ips 93.190.95.241
</IfModule>

Links

Load-Balancing

Der Begriff Load-Balancing beschreibt eine Methoden zur Lastverteilung auf mehrere getrennte Server im Netzwerk. Die nachfolgende Anleitung (Doku) ist noch in Bearbeitung. Bei Fragen bitte an DocX wenden.

Konfiguration LB

Installation Betriebssystem

Debian 5.0 (netinstall) mit Standart-System

Installation zusätzlicher Software-Pakete

apt-get install heartbeat-2 ldirectord-2

Datei /etc/hosts bearbeiten

127.0.0.1      localhost
192.168.0.10   lb01    lb01.piratenpartei-nrw.de
192.168.0.20   lb02    lb02.piratenpartei-nrw.de

ha.cf

logfacility        local0
bcast        eth0
mcast eth0 225.0.0.1 694 1 0
auto_failback off
node        lb01
node        lb02
baud        9600
serial      /dev/ttyS0
respawn hacluster /usr/lib/heartbeat/ipfail
apiauth ipfail gid=haclient uid=hacluster

haresources

lb01 \
        ldirectord::ldirectord.cf \
        LVSSyncDaemonSwap::master \
        IPaddr::192.168.0.1/24/eth0/192.168.0.255 \
        IPaddr::192.168.0.2/24/eth0/192.168.0.255 \
        IPaddr::192.168.0.3/24/eth0/192.168.0.255 \
                SMSbyMail::


ldirectord.cf

checktimeout=5
checkinterval=2
autoreload=no
logfile="local0"
quiescent=yes

#
# www.piratenpartei-nrw.de (non-ssl)
#
virtual=192.168.0.1:80
        real=192.168.0.100:80 gate
        real=192.168.0.200:80 gate
        service=http
        request="ldcheck.php"
        receive="running"
        scheduler=rr
        protocol=tcp
        checktype=negotiate

#
# www.piratenpartei-nrw.de (ssl)
#
virtual=192.168.0.1:443
        real=192.168.0.100:443 gate
        real=192.168.0.200:443 gate
        service=https
        request="ldcheck.php"
        receive="running"
        scheduler=rr
        protocol=tcp
        checktype=negotiate
 
#
# nrw.klarmachen-zum-aendern.de (non-ssl)
#
virtual=192.168.0.2:80
        real=192.168.0.100:80 gate
        real=192.168.0.200:80 gate
        service=http
        request="ldcheck.php"
        receive="running"
        scheduler=rr
        protocol=tcp
        checktype=negotiate

#
# nrw.klarmachen-zum-aendern.de (ssl)
#
virtual=192.168.0.2:443
        real=192.168.0.100:443 gate
        real=192.168.0.200:443 gate
        service=https
        request="ldcheck.php"
        receive="running"
        scheduler=rr
        protocol=tcp
        checktype=negotiat

#
# mail.piratenpartei-nrw.de (non-ssl)
#
virtual=192.168.0.3:80
        real=192.168.0.100:80 gate
        real=192.168.0.200:80 gate
        service=http
        request="ldcheck.php"
        receive="running"
        scheduler=rr
        protocol=tcp
        checktype=negotiate

#
# mail.piratenpartei-nrw.de (ssl)
#
virtual=192.168.0.3:443
        real=192.168.0.100:443 gate
        real=192.168.0.200:443 gate
        service=https
        request="ldcheck.php"
        receive="running"
        scheduler=rr
        protocol=tcp
        checktype=negotiate

sysctl.conf

kernel.panic = 5
kernel.domainname = piratenpartei-nrw.de
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.ip_forward = 1

/root/.bashrc

alias _status='/usr/sbin/ldirectord /etc/ha.d/ldirectord.cf status'
alias _lb='/sbin/ipvsadm -L'

Konfiguration Webserver

/etc/network/interfaces erweitern

# The LinuxVirtualServer Address

## www.piratenpartei-nrw.de
auto lo:0
  iface lo:0 inet static
  address 192.168.0.1
  netmask 255.255.255.255
  pre-up sysctl -p > /dev/null

# nrw.klarmachen-zum-aendern.d
auto lo:1
  iface lo:1 inet static
  address 192.168.0.2
  netmask 255.255.255.255

# mail.piratenpartei-nrw.de
auto lo:2
  iface lo:2 inet static
  address 192.168.0.3
  netmask 255.255.255.255

/etc/sysctl.conf

kernel.panic = 5
kernel.domainname = wiki.piratenpartei.de
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.tcp_syncookies = 1

net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2

net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2

Mail von Andy zum Thema PHP Cache

bzgl. des PHP-Turboladers habe ich mich mit meinem befreundeten PHP-Gott (Entwickler von s9y und Mitentwickler u.a. von phpmyadmin) unterhalten, und er hat mich u.a. darauf hingewiesen, daß turck-mmcache seit Jahren nicht weiterentwickelt wird sondern geforked wurde.

_DER_ PHP-Accelerator dieser Tage ist der APC, welcher mit Abstand am aktivsten entwickelt wird, als erster PHP5 unterstützt hat, und in PHP6 auch defaultmässig dabei sein wird.

Es gibt fertige Debian-Pakete des APC. Den nehmen, und gut.

Pro und Contra, und grundsätzliche Wirkungsweise eines PHP-Beschleunigers kann ich auf der Webcache-Seite unserer Wiki-Seite ggf. mal nachtragen. Bis dahin verweise ich auf diese beiden Seiten der englischen Wikipedia:

http://en.wikipedia.org/wiki/PHP_accelerator http://en.wikipedia.org/wiki/List_of_PHP_accelerators

Komplexität, Wartungsaufwand und mögliche Sicherheits-Probleme sind Gründe gegen einen PHP-Turbolader. Gründe dafür ist die Performance-Steigerung, die bei 10 bis 1000 liegt; bei unseren erwarteten Hitzahlen ists keine Frage, sondern eine Notwendigkeit: ohne so nen Turbolader muss man schnell clustern. Auf einem älteren Root-Server von mir war der APC (früher Turck) schon öfters der Unterschied zwischen "geht wunderbar" und timeout. Konfiguration ist kinderleicht, in der Regel ists mit einer load-Zeile in der php.ini (bzw. apt-get install apc-..) des Webservers getan, das finetuning abseits der default-Vorgaben kann, nicht muss.

Unabhängig davon sind natürlich Caching-Mechanismen auf http-Ebene (squid, vanish) sowie applikationseigene Caching-Mechanismen z.B. bei CMS oder bei uns Wordpress. Von s9y kenne ich die caching-Funktionalität, daß die Seiten nicht für jeden Aufruf einzeln generiert sondern eben gecached sowie in konfigurierbaren Intervallen (z.B. 15 Minuten) neue dann statische Seiten generiert werden. Sowas nimmt natürlich auch nochmal extrem Last weg, ich würde mich wundern wenn WP das nicht auch könnte.

Meiner Meinung nach sollten wir alles ausreizen: squid, wp-caching, APC. Wenn wirklich Tausende Piraten auf dem Piraten-NRW-Server rumturnen, gehts imho auch nicht ohne.