Scratchbook

Das Leben ist immer anders als die Realität.

Loadbalancer, die keine sind

Claude, 30. November 2012, 09:49 Uhr

Warning: Use of undefined constant ri_rand_compare - assumed 'ri_rand_compare' (this will throw an Error in a future version of PHP) in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/random-image-widget/random_image.php on line 129 Warning: Use of undefined constant ri_rand_compare - assumed 'ri_rand_compare' (this will throw an Error in a future version of PHP) in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/random-image-widget/random_image.php on line 130 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 1384 Warning: preg_match_all(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 700 Warning: Invalid argument supplied for foreach() in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 707 Warning: preg_match_all(): Compilation failed: invalid range in character class at offset 4 in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 700 Warning: Invalid argument supplied for foreach() in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/plugins/lightbox-plus/classes/shd.class.php on line 707

Viele Web- und Proxyserver bringen eine Loadbalancerfunktion mit. Mit Session-Stickyness. „Hach wie praktisch“, könnte man denken. Leider funktioniert das nicht immer so wie es im Handbuch steht.

Ein Loadbalancer (Lastverteiler) ist dazu da, viele Anfragen auf mehrere Server zu verteilen, um den Durchsatz und die Ausfallsicherheit zu erhöhen. Knifflig wird es, wenn auf einem Server benutzerspezifische Informationen gespeichert werden, zum Beispiel ein Warenkorb – dann muss der Loadbalancer nämlich alle Anfragen dieses Benutzers immer auf den gleichen Server weiterleiten, auf dem der Warenkorb gespeichert ist, damit der erhalten bleibt.
Bei einem bekannten Onlineshop hatten wir kürzlich das Problem, dass bei einigen Bestellungen plötzlich der Warenkorb leer ist, sobald der Benutzer versucht, sich einzuloggen. Beim Login wechselt die Seite auf eine SSL-Verbindung – kann also gut sein, dass der Loadbalancer die Verbindung auf einen anderen Server leitet und die Session mit dem Warenkorb verloren geht. Ich probiere das gleich aus.

„Bei mir lokal läufts.“

Klick auf Login. Der Browser wechselt auf https. Es sind noch alle Waren im Korb. Auch bei Tests von anderen Rechnern aus. Das Problem lässt sich sehr schwer nachstellen. Offenbar tritt das Phänomen nur zu gewissen Uhrzeiten und meistens bei Benutzern aus Singapur auf.

Wie sieht denn die Konfiguration aus? Vor zwei Tomcat Hybris Nodes steht ein Nginx, der sich um die Terminierung der SSL-Verbindungen und um die Lastverteilung kümmert:

Wenn jetzt also ein Benutzer Artikel zum Warenkorb hinzufügt, werden die in einer Session gespeichert, z.B. auf Node 1. Falls der Loadbalancer die Verbindung bei einem Wechsel nach SSL auf den anderen Node leitet, ist die Session dort nicht vorhanden und wird neu erzeugt, der Warenkorb ist leer.

Nginx ist so konfiguriert, dass eine Benutzer-IP immer auf dem gleichen Server landet.
Was passiert, wenn sich die IP-Adresse eines Benutzers ändert? Das ist sehr unwahrscheinlich, und wir glauben auch nicht so recht dran. Aber Singapur hat Proxies und Zensurinfrastrukturen, und so entschliessen wir uns, auf ein Cookie-basiertes Loadbalancing umzustellen.

Gar nicht mal so einfach. Nginx bringt das von Haus aus nicht mit. Man muss ein externes Modul mit einkompilieren.

Gesagt, getan. Die Cookie-basierte Stickyness ist installiert. Und was macht Nginx?
Ich teste.
Jetzt kann ich das Problem auch bei mir Nachstellen; der Warenkorb wird ab und zu geleert! Das funktioniert überhaupt nicht. Ausserdem erzeugt Nginx jetzt pro URL-Pfad ein Cookie. Tolle Session-Stickyness 🙁

So langsam gehen uns die Ideen aus. Wir haben auf den Hybris Nodes ein erweitertes Logging eingerichtet, welches die Sessions überwacht. Kein Fehler von dieser Seite. Der Hoster weiss auch nicht weiter. Es wird langsam eng. Was haben wir noch für Möglichkeiten?

Ich teste den Memcached Session Manager bei mir und stelle das Szenario nach. Es funktioniert nicht immer; das ganze dünkt mich sehr wackelig.

Noch zwei Varianten.

Varnish? Varnish. Der kann zwar keine SSL-Verbindungen terminieren, aber wenn ich den zwischen Nginx und die Hybris-Nodes stelle, dann macht Nginx weiterhin SSL, und Varnish kümmert sich um die korrekte Verteilung der Sessions.

Eigentlich wäre es ganz einfach, sagt das Handbuch:

set client.identity = req.http.cookie;

Von wegen, nix is! Bunt durchmischt landen die Anfragen mal auf Node 1, mal auf Node 2. Das scheint überhaupt nicht zu funktionieren. Ich bin enttäuscht. Vermutlich generiert Varnish eine Prüfsumme auf den Cookie-Header, und wenn unsere Anal-ytics-Software auf dem Browser ihre Kekse schmeisst, wirbelt es diese Prüfsummen durcheinander. Grossartig.

Gopferdammi, das kann doch nicht so schwer sein?! Langsam zweifle ich an meinen Fähigkeiten. Ich komme mir langsam richtig dumm vor. Sessionbasiertes Loadbalancing; andere machen das doch auch, warum funktioniert das bei uns nicht? Ich google bis zur fünfundreissigsten Suchresultatsseite. Loadbalancing Nginx. Loadbalancing Varnish. Webforen, Mailinglisten. Alle behaupten steif und fest, dass das mit client.identity funktioniert. Nein, liebes Internet, das tut es nicht.

Noch eine Variante.

HAProxy. Ich habe bislang nur davon gelesen, „dass es das gibt“. Kann ja mal einen Versuch wagen.

Und ich wurde positiv überrascht. Er ist schnell installiert, die Dokumentation ist allererste Sahne, und eine Zugfahrt später habe ich eine Konfiguration ausprobiert und stelle nach intensiven Tests fest: Die Warenkörbe bleiben erhalten!

HAProxy ist zwar „nur“ ein Loadbalancer – aber DAS macht er richtig gut! Der bietet nicht nur Cookie-basiertes Loadbalancing an; ich kann gleich zwischen verschiedenen Cookie-Strategien auswählen. Will ich intern eine Tabelle mit allen JSESSION-IDs führen? Soll ein Loadbalancer-Cookie an den Client geschickt werden, damit er erkennt, auf welchem Node der Client seine Session hat? Gewichtetes Loadbalancing, ausgefeilte Failover-Strategien, alles kein Problem. Eine Statusseite ist auch mit dabei. Die HTTP-Header werden normalisiert, damit sie einheitlich daherkommen. Ein sehr durchdachtes Stück Software.

Die neue Konfiguration sieht wie folgt aus:

Nginx nimmt wie gehabt alle Anfragen inkl. SSL-Verbindungen entgegen. Leitet aber nur noch an den HAProxy weiter. Der leitet dann die Verbindungen korrekt an die Nodes weiter und sorgt dafür, dass die Warenkörbe voll bleiben. Voilà: Die Kunden aus Singapur können bestellen.

Merke:

  • Use the right tool for the job. Es gibt Werkzeuge, die sind genau für einen Zweck geschaffen. Und den erfüllen sie richtig gut. Nginx für SSL-Terminierung. Varnish für Caching. Und HAProxy für Loadbalancing.
  • Mitgelieferte Beilagen und Nebenfunktionen funktionieren nicht immer. Vorallem nicht, wenn man sie als Hauptfunktion einsetzen will. Das wird auf Dauer zu unflexibel.
  • Vertrau‘ keinem Handbuch. Ja, dort drin steht, das müsste so funktionieren. TUT ES ABER NICHT.
Warning: count(): Parameter must be an array or an object that implements Countable in /home/httpd/vhosts/scratchbook.ch/httpdocs/wp-content/themes/scratchbook/navigation_bar_bottom.php on line 1