Aus Linux-Magazin 09/2008

Eine Webapplikation für extreme Lasten optimieren

© daniel.schoenen, Photocase.com

Wie geht ein Systemarchitekt vor beim Design eines dynamischen Webauftritts, bei dem binnen kurzer Zeit achtstellige Seitenabrufe zu erwarten sind? Wenn zudem 38000 gechipte Marathonläufer die dahinterliegende Datenbank in Echtzeit füttern, ahnt man: Das Ganze muss gleich beim ersten Versuch klappen.

Einen Webserver mit Datenbankanbindung konfigurieren ist eine Übung für Anfänger. Ein System allerdings, das innerhalb weniger Stunden 15 Millionen Seitenabrufe verkraften soll, verlangt auch vom Profi sorgfältige Vorbereitung, eine exakte Projektplanung und praxisnahe Last- und Performancetests.

Besondere Lastprofile

In jedem Fall sind es die Nutzer, die das Auslastungsprofil einer Webapplikation prägen. So sorgen die Besucher von Social-Networking-Sites wie Stayfriends oder Classmates besonders in den Abendstunden für Traffic, während die Webpräsenz einer großen IT-Firma hauptsächlich tagsüber Nutzer bedient. Wieder andere Anforderungen resultieren aus Webauftritten, die bestimmte Events unterstützen sollen und im Zusammenhang mit dem Ereignis kurzzeitig sehr hohe Lasten aushalten müssen.

Im Beispiel, das dieser Beitrag vorstellt, geht es um die Ergebnispräsentation beim New York Marathon Anfang November letzten Jahres und bei ähnlichen Großveranstaltungen, wie sie auch Chicago oder London ausrichten und damit jeweils mehrere Zehntausend Läufer anziehen. Der Zeitnehmer dieser Läufe hatte das Team des Autors engagiert, um eine Datenbanklösung nebst Webinterface für die Darstellung der Ergebnisse zu entwickeln und zu hosten.

Während der Marathons erfassenten Messmatten im Streckenverlauf die Zeit, sobald ein Chip-bestückter Läufer sie überquerte. Dabei aktivierte sich ein batterieloser, nur vier Gramm schwerer Transponder am Schuh durch das Magnetfeld der Matte und sendete seine Kennung. Diese Daten gelangten zuerst auf einen lokalen Server und wurden dann – nach einigen Zwischenberechnungen und Prüfungen – fast in Echtzeit nach Nürnberg ausgeliefert. Bei über 38000 Läufern im Ziel ergab dies allein ein Vielfaches an Datenbank-Updates.

Diese Menge war zudem sehr zeitnah zu bewältigen, denn vereinbart war eine Seiten-Auslieferungszeit von unter einer Sekunde, was gleichzeitig für die Serverarchitektur, den Replikationsmechanismus und die Webprogrammierung den Richtwert vorgab.

Umsetzung

Die Linux-typische Lösung ist der Aufbau einer hochverfügbaren Webapplikation mit Load-Balancer-Cluster, Webserverfarm und hochverfügbarer Datenbank (Abbildung 1). Bei der Komponentenauswahl lag der Fokus vor allem auf den Kriterien Performance, Skalierbarkeit, Einfachheit und Modularität.

Abbildung 1: Der prinzipielle Aufbau der Webapplikation, die inzwischen bei verschiedenen Groß-Marathons millionenfache Zugriffe in kurzer Zeit verkraftet hat.

Abbildung 1: Der prinzipielle Aufbau der Webapplikation, die inzwischen bei verschiedenen Groß-Marathons millionenfache Zugriffe in kurzer Zeit verkraftet hat.

Vergleichswerte von früheren Veranstaltungen gab es nicht. Deshalb ließ sich nur über Lasttests ermitteln, ob die vorgesehenen Komponenten die Belastung verkraften würden. Aber auch dabei war es nicht möglich, die Last von 140 000 parallelen Anwendern tatsächlich zu simulieren. Stattdessen war nur eine kleinere Testkonfiguration verfügbar, anhand derer die Systemarchitekten die erwarteten Verhältnisse hochrechneten. Wie sich später zeigte, gelang aber trotzdem eine ziemlich genaue Annäherung an die reale Belastung.

Die fertige Umgebung für den Betrieb der Webapplikation bestand dann schließlich aus zwei Load Balancern, sechs Applikationsservern sowie zwei Datenbankservern. Für die Lasttests selbst kam Apache JMeter [1] zum Einsatz, das alle notwendigen Prüfungen – die so genannten Sampler – für detaillierte Last- und Performancetests bereits mitbringt.

Drei Kriterien waren besonders wichtig, um ein realistisches Nutzerverhalten zu simulieren: Als erstes waren dynamische Abfragewerte erforderlich, um die Suche nach Läufern oder Messpunkten im Frontend nachzubilden. Eine Abfrage mit einer beschränkten Anzahl von statischen Werten hätte die Datenbank aus dem Query- und Buffercache bedient und so das Ergebnis verfälscht. Um dieses Problem zu umgehen, benutzte das Team ein CSV-File mit zufällig erzeugten Abfragewerten, die dann über Variablen in die HTTP-Requests einflossen.

Zweite wichtige Vorraussetzung war eine bestimmte Parallelität der Anfragen, wie sie auch in der Realität zu erwarten sind. Das bewerkstelligten mehrere JMeter-Slaves (Abbildung 2), die zeitgleich die Server auf die Probe stellten. Und drittens galt es, eine realistische Query- undReplikationslast auf den Datenbankservern zu erzeugen. Bereits die ersten Tests hatten gezeigt, dass die Replikation der importierten Daten einen wesentlichen Einfluss auf die Performance der gesamten Plattform hat.

Abbildung 2: Mehrere JMeter-Slaves beanspruchen die Webapplikation im Test parallel – ganz ähnlich wie das auch in einer realen Lastsituation zu erwarten wäre.

Abbildung 2: Mehrere JMeter-Slaves beanspruchen die Webapplikation im Test parallel – ganz ähnlich wie das auch in einer realen Lastsituation zu erwarten wäre.

Balanceakt

Die Notwendigkeit, in kurzer Zeit viele Webservice-Anfragen zu beantworten und gleichzeitig die Applikation hochverfügbar abzusichern, führte zu einem Konzept, das beide Aspekte durch die Kombination von Load Balancing mit Linux Virtual Server (LVS, [2]) und Hochverfügbarkeit durch Heartbeat [3] als Clustermanager berücksichtigt.

Die Load-Balancer-Knoten überwachen sich gegenseitig über eine dedizierte Netzwerkverbindung und ein serielles Kabel. Die Verfügbarkeit des Internets fließt ebenfalls in den Knotenstatus ein. Damit Clients auch dann den Applikationsserver erreichen, wenn einer der Load Balancer ausgefallen sein sollte, sorgt der zum LVS gehörende »syncmaster«-Daemon für die Synchronisation der Netzwerkverbindungen.

Diese Synchronisierung erledigt er mittels Multicast vom aktiven System aus, der dafür nötige Daemon läuft als Kernelprozess. Eine Beeinträchtigung der Performance des Load Balancers war nicht feststellbar. Der Syncmaster-Dienst muss auch auf allen Backup-Knoten laufen – die Kennzeichnung als Master oder Slave übernimmt das Heartbeat-Resourceskript allerdings automatisch.

Die Verfügbarkeitsprüfung der Server im Load-Balancer-Pool erledigt »ldirectord« [4]. Dazu ist auf jedem der Applikationsserver eine Testseite abgelegt, die die Load Balancer regelmäßig abfragen (im Beispiel alle fünf Sekunden). Nach jeder Anfrage hilft ein Vergleich des Texts der Testseite jene Webserver zu erkennen, die noch auf Anfragen reagieren, aber keine Inhalte mehr liefern. Ein ausgefallenes System müsste den Pool verlassen, die ankommenden Verbindungen verteilen sich auf die verbliebenen Server. Den Start der Dienste »syncmaster« und »ldirectord« übernimmt Heartbeat.

Um die Applikation zusätzlich auch unter kurzzeitig extremer Last stabil verfügbar zu halten, griff das Team des Autors zu einem Trick. Es fügte dem Pool einige Webserver mit statischen HTML-Inhalten hinzu. Diese Webserver fungieren als eine Art Überdruckventil. Im Normalbetrieb haben sie eine Gewichtung von »0«, was bedeutet, dass sie keine Anfragen vom Load Balancer erhalten.

Bei Lastspitzen erhöht sich jedoch ihre Gewichtung und die Load Balancer leiten einen bestimmten Teil der Anfragen auf sie um. Die statischen Server parken die Anfragen für kurze Zeit und geben sie dann wieder in den Pool zurück. Beruhigt sich die Situation, verringert sich die Gewichtung dieser Webserver wieder langsam bis auf null.

Die Datenbank

Um die Datenbanklast nicht auf einem einzelnen zentralen Datenbankserver verarbeiten zu müssen, konfigurierte das Team eine MySQL-Instanz [5] pro Applikationsserver. Der zentrale Datenbankcluster für den Datenimport repliziert sämtliche Aktualisierungen auf jeden der beiden Applikationsserver.

Die hohe Replikationslast führte während der Lasttests unter MySQL 5.0 und der dort verwendeten Statement-based Replication nach kurzer Zeit zu einer für die Anwendung bereits kritischen Replikationsverzögerung. Ein Upgrade auf die MySQL-Version 5.1 mit der dort neu eingeführten Mixed Replication konnte dieses Replication Lag beseitigen.

Bei diversen Tests mit mehreren Datenbank-Engines (Heap, MyISAM, Inno DB) erwies sich Inno DB in diesem Fall als beste Wahl. Außerdem erwogen die Tester, ob es möglich und sinnvoll wäre, die Inno-DB-Datafiles im Shared Memory abzulegen. Es zeigte sich allerdings, dass diese Methode gegenüber dem Speichern auf der Festplatte nur geringe Performancevorteile bringen würde. Außerdem stand dem der gravierende Nachteil gegenüber, dass nach einem Ausfall oder einem Reboot eines der Applikationsserver dessen Datenbankdaten verloren und anschließend komplett neu zu importieren gewesen wären.

Auf die Optimierung der Datenbankinstanzen legten die Mitarbeiter ebenfalls großen Wert. So banden sie zum Beispiel das Filesystem der Data-Files mit gesetztem »Noatime«-Flag ein. Dadurch aktualisiert nicht jeder Zugriff auf die Inno-DB-Dateien automatisch den Zeitstempel im Dateisystem.

Außerdem optimierten sie die Inno-DB-spezifischen MySQL-Parameter. Dabei setzten sie etwa auf den Applikationsservern die Parameter »innodb_flush_log_at_trx_commit« und »innodb_support_xa« auf null, um die I/O-Last der Systeme zu verringern. Zur Beschleuniging des Imports der Dateien auf dem MySQL-Master/Master-Cluster konfigurierten sie dort »SET AUTOCOMMIT=0;«. Das unterdrückt zwischenzeitliche Bestätigungen und verschiebt den nötigen Commit ganz an den Schluss. Er wird dann erst ausgeführt, wenn alle anstehenden Datensätze abgearbeitet sind.

Beim Ausliefern der PHP-Webseiten an die Clients zeigte sich Lighttpd [6] zusammen mit Fast CGI und PHP 5 schneller und effizienter als Apache in der Prefork-Variante. Getestet wurden beide Webserver in der von Debian Etch mitgelieferten Version. Für die Zwischenspeicherung der durch PHP generierten statischen Inhalte der Seiten kam »eaccelerator« zum Einsatz.

Bei der Programmierung der Anwendung achteten die Entwickler darauf, möglichst viele Elemente auf dem Client zu cachen. Zudem sorgten sie dafür, dass sich in einer Überlast-Situation besonders Ressourcen-intensive Features wie ein Leaderboard oder detailgenaue Suchoptionen zur Laufzeit deaktivieren lassen.

Abbildung 3: Die Webserver-Statistik wies am Ende mehr als 15 Millionen Seitenabrufe in wenigen Stunden aus. Das System hielt dieser Last jedoch jederzeit problemlos stand.

Abbildung 3: Die Webserver-Statistik wies am Ende mehr als 15 Millionen Seitenabrufe in wenigen Stunden aus. Das System hielt dieser Last jedoch jederzeit problemlos stand.

Ziel erreicht

Der Tag der Veranstaltung machte schnell klar, dass sich die Vorbereitungen gelohnt hatten. Allein innerhalb der ersten acht Stunden lieferten die Server rund 15 Millionen Pageviews (Abbildung 3) an über 215 000 Besucher. Bei einer hohen durchschnittlichen Verweildauer der User auf der Website von 45 Minuten verließen rund 70 Seiten pro Benutzer die Systeme. Trotz der hohen Auslastung erreichten weder Datenbanksubsystem noch die Webserver die erwarteten Auslastungsgrenzen. Dank der Mixed-Mode-Replikation führte auch eine starke Aktualisierungsfrequenz nicht zu Slave Lags bei der Replikation. Das vereinbarte SLA wurde eingehalten, die anvisierte Auslieferungszeit von maximal einer Sekunde pro Seite weit unterboten. (jcb)

Infos

[1] JMeter: [http://jakarta.apache.org/jmeter/]

[2] LVS: [http://www.linuxvirtualserver.org]

[3] Heartbeat: [http://linux-ha.org]

[4] Ldirectord: [http://www.vergenet.net/linux/ldirectord/]

[5] MySQL: [http://www.mysql.com]

[6] Lighttpd: [http://lighttpd.net]

[7] Netways: [http://www.netways.de]

Der Autor

Bernd Erk ist technischer Leiter der Nürnberger Netways GmbH, die auch das hier vorgestellte Setup entwickelt hat.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 3 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben