Apache: Erstellen eines Session-kompatiblen Loadbalancers unter Verwendung von mod_proxy_balancer (Debian Etch)

Version 1.0
Author: Falko Timme


Seit Apache Version 2.1 ist ein neus Modul namens mod_proxy_balancer verfügbar, mit dem Du ein System, auf dem Apache installiert ist, in einen Loadbalancer umwandeln kannst. Dieser Loadbalancer ruft angeforderte Seiten von einem oder mehreren backend Web Servern auf und sendet sie an den Computer des Benutzers. Benutzer gewinnen den Eindruck,  dass sie sich nur mit einem Server (dem Loadbalancer) beschäftigen, obwohl hinter dem Loadbalancer eigentlich mehrere Systeme stehen, die die Anfragen des Benutzers ausführen. Mit einem Loadbalancer kannst Du die durchschnittliche Auslastung auf Deinen Web Servern verringern. Eine wichtige Funktion von mod_proxy_balancer ist, dass es Sessions verfolgen kann, was bedeutet, dass es ein Benutzer immer mit dem gleichen backend Web Server zu tun hat. Die meisten Webseiten sind heutzutage Datenbank-basiert mit Benutzer Logins etc. Man würde komische Ergebnisse erhalten, wenn sich ein Benutzer auf einem backend Web Server anmeldet und seine nächste Anfrage dann zu einem anderen backend Web Server gesendet wird, was bedeutet, dass er wieder abgemeldet wird. Das kannst Du mit mod_proxy_balancer verhindern.

Ich übernehme keine Garantie, dass dies auch bei Dir funktioniert!

1 Vorbemerkung

Es sollte zur Kenntnis genommen werden, dass ein Loadbalancer die Auslastung auf Deinen backend Web Servern verringern kann, er bietet allerdings keine hoch-Verfügbarkeit an (solange Du nur einen Loadbalancer verwendest)! Ein einzelner Loadbalancer ist eine Schwachstelle. Wenn Du eine hoch-Verfügbarkeit möchtest, solltest Du mindestens zwei Loadbalancer (z.B. einen als hot-standby) verwenden.

Ich werde in diesem Beispiel drei Server verwenden: einen Loadbalancer mit der Adresse www.example.com / example.com und zwei backend Server mit den Adressen http1.example.com und http2.example.com.

Alle drei Server verwenden Debian Etch als Betriebssystem und auf allen drei Systemen ist Debians Apache2 installiert (die Version ist 2.2.3,  mod_proxy_balancer ist also standardmäßig integriert). Auf http1.example.com und http2.example.com habe ich eine Datenbank-basierte Web Anwendung installiert: phpBB2, eine beliebte Forum Software. Beide phpBB2 Installationen sind identisch und verwenden die gleiche Datenbank. Für die Fehlersuche habe ich in beiden Installationen einen kleinen Unterschied eingebaut: Wenn die Seite von http1.example.com zugestellt wird, wird http1.example.com im Header angezeigt:


Und wenn sie von http2.example.com zugestellt wird, wird http2.example.com angezeigt:


Somit kann ich kontrollieren, ob Sessions von mod_proxy_balancer richtig gehandhabt werden. Auf einem Produktionssystem wären beide Seiten natürlich gleich.

Das Verfolgen der Sessions ist in mod_proxy_balancer etwas knifflig, da es ein bestimmtes Cookie Format erwartet und der Name der Sessionvariable von Anwendung zu Anwendung unterschiedlich sein kann. Gott sei Dank habe ich diese Seite gefunden: http://www.markround.com/archives/33-Apache-mod_proxy-balancing-with-PHP-sticky-sessions.html die eine großartige und einfache Lösung für dieses Problem bereit hält, die ich hier anwenden werde.

2 Die Backend Server vorbereiten

Zuerst müssen wir unsere backend Web Server http1.example.com und http2.example.com vorbereiten. Wir aktivieren mod_rewrite wie folgt:

http1.example.com / http2.example.com:

a2enmod rewrite
/etc/init.d/apache2 force-reload

Dann öffnen wir die Apache vhost Konfiguration unserer phpBB2 Site auf http1.example.com und fügen folgende Zeilen hinzu:

http1.example.com:

[...]
RewriteEngine On RewriteRule .* - [CO=BALANCEID:balancer.http1:.example.com] [...]
(Pass auf, dass Du http1 und .example.com entsprechend Deiner Vorstellungen ersetzt!)

Starte Apache danach neu:

http1.example.com:

/etc/init.d/apache2 restart

Jetzt führen wir das Gleiche auf http2.example.com aus:

http2.example.com:
[...]
RewriteEngine On RewriteRule .* - [CO=BALANCEID:balancer.http2:.example.com] [...]
(Pass auf, dass Du http2 und .example.com gemäß Deinen Vorstellungen ersetzt!)

Starte Apache danach neu:

http2.example.com:

/etc/init.d/apache2 restart

Mehr müssen wir auf den backend Servern nicht konfigurieren.

3 Konfiguration des Loadbalancers

Auf unserem Loadbalancer www.example.com müssen wir einige Apache Module aktivieren:

www.example.com:

a2enmod proxy
a2enmod proxy_balancer
a2enmod proxy_http
a2enmod status

und starten dann Apache neu:

/etc/init.d/apache2 force-reload

Ich gehe davon aus, dass wir auf dem Loadbalancer keine anderen Webseiten ausführen, also können wir Debians Standard Dokumenten-Root /var/www für unseren Loadbalancer verwenden.

mod_proxy_balancer hat einen "Balancer Manager", ein kleines Web Interface, auf dem Du ein paar Einstellungen optimieren kannst. Wir erstellen dafür das Verzeichnis /var/www/balancer-manager, das wir mit einem Passwort schützen, so dass nur wir Zugriff darauf haben:

mkdir /var/www/balancer-manager
htpasswd -c /var/.htpasswd admin

(Du kannst admin mit einem beliebigen Benutzernamen ersetzen.)

vi /var/www/balancer-manager/.htaccess


AuthType Basic
AuthName "Members Only" AuthUserFile /var/.htpasswd <limit GET PUT POST> require valid-user </limit>
Nun kommen wir zur vhost Konfiguration des Loadbalancers. Apaches Standard vhost Konfiguration auf Debian Etch  befindet sich in /etc/apache2/sites-available/default, also ersetzen wir sie mit unserer eigenen Konfiguration:

cp /etc/apache2/sites-available/default /etc/apache2/sites-available/default_orig
cat /dev/null > /etc/apache2/sites-available/default
vi /etc/apache2/sites-available/default

NameVirtualHost *
<VirtualHost *> ServerName www.example.com ServerAlias example.com DocumentRoot /var/www/ ProxyRequests Off <Proxy *> Order deny,allow Allow from all </Proxy> ProxyPass /balancer-manager ! ProxyPass / balancer://mycluster/ stickysession=BALANCEID nofailover=On ProxyPassReverse / http://http1.example.com/ ProxyPassReverse / http://http2.example.com/ <Proxy balancer://mycluster> BalancerMember http://http1.example.com route=http1 BalancerMember http://http2.example.com route=http2 ProxySet lbmethod=byrequests </Proxy> <Location /balancer-manager> SetHandler balancer-manager Order deny,allow Allow from all </Location> </VirtualHost>
Es ist sehr wichtig, dass Du alle Slashes  (/) GENAUSO wie im Beispiel gezeigt wird setzt, vor allem die Slashes am Ende von Adressen!


Bitte pass auf, dass der Wert von stickysession der Name des Cookies (BALANCEID) in unseren Rewrite Regeln von Kapitel 2 ist. Weiterhin müssen die Werte von route in den BalancerMember Zeilen den entsprechenden Wert aufweisen, den wir in den Rewrite Regeln (http1 oder http2) eingestellt haben. Die stickysession und route Werte achten auf die richtige Session-Handhabung von mod_proxy_balancer.

Außerdem ist wichtig, dass Du genauso viele ProxyPassReverse Zeilen wie BalancerMember Zeilen hast (eine ProxyPassReverse Zeile für jeden BalancerMember).

Die ProxyPass /balancer-manager ! Zeile stellt sicher, dass Anfragen auf www.example.com/balancer-manager nicht an die backend Server gerichtet werden.

Mehr Informationen über alle Einstellungen und weitere Optimierungsoptionen findest Du auf  http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypass und http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html.

Da wir nun die Konfiguration abgeschlossen haben, müssen wir Apache neu starten:

/etc/init.d/apache2 restart


4 Unser Setup testen

Unser Setup kann nun verwendet werden. Um herauszufinden, ob Sessions richtig gehandhabt werden, öffne ich zwei unterschiedliche Browser (wegen der Cookies), z.B. Firefox und Internet Explorer und gehe zu http://www.example.com oder http://example.com. In beiden Fällen müsstest Du das phpBB2 Forum sehen, das von einem der backend Server zugestellt wurde (was man nicht sieht, Du müsstest immer www.example.com oder einfach example.com in der Adresszeile des Browsers  stehen haben).

Es kann sein, dass die Seiten in beiden Browsern vom gleichen backend Server geliefert werden - wenn das der Fall ist, dann lösche die Cookies in Deinen Browsern oder öffne einen anderen Browser (Opera, Seamonkey, ...) und versuch es erneut bis Du siehst, dass die Seiten in Deinen unterschiedlichen Browsern von verschiedenen backend Servern stammen (ich kann das sehen, weil ich den Header geändert habe, wie in Kapitel 1 beschrieben). Melde Dich dann mit zwei unterschiedlichen Benutzern an (z.B. falko und till), die Du zuvor erstellt hast, und durchforste das Forum mit diesen beiden Benutzern. In meinem Fall wird falkos Inhalt immer von http1.example.com geliefert:


Wohingegen tills Inhalt von http2.example.com stammt:


Als werden Session von mod_proxy_balancer richtig gehandhabt!

5 Der Balancer Manager

Richte Deinen Browser auf http://www.example.com/balancer-manager oder http://example.com/balancer-manager. Du wirst nach einem Benutzernamen und Passwort gefragt (der Benutzername und das Passwort, das Du in Kapitel 3 erstellt hast).

Nach dem Login siehst Du ein einfaches Web Interface mit dem Du den Loadbalancer managen kannst:




Einen Überblick über mögliche Konfigrationsoptionen findes Du auf  http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypass.

6 Links