BLOG

Die fünf wichtigsten Skalierbarkeitsmuster

Lori MacVittie Miniaturbild
Lori MacVittie
Veröffentlicht am 30. Mai 2018

In einer Wirtschaft, in der Anwendungen die Währung sind, ist Verfügbarkeit eine ernste Angelegenheit. Apps, die nicht reagieren, werden kurzerhand gelöscht und im Internet mit der Geschwindigkeit und dem Sarkasmus einer negativen Yelp-Rezension schlechtgemacht.

Seit den Anfängen des Internets haben Unternehmen versucht, die Verfügbarkeit ihrer Anwendungen (früher Websites) an 365 Tagen im Jahr rund um die Uhr sicherzustellen. Denn das Internet schläft nie, macht nie Urlaub und meldet sich nie krank.

Um diesem Bedürfnis (eigentlich dieser Anforderung) gerecht zu werden, entwickelte sich Skalierbarkeit zu einem der ersten Anwendungsdienste, der für Verfügbarkeit sorgte. Der sichtbarste – und am besten verstandene – Anwendungsdienst, der den Anforderungen an die Verfügbarkeit dient, ist der Lastausgleich.

Es gibt jedoch viele Formen des Lastausgleichs und Skalierbarkeitsmuster, die Sie mit dieser Kerntechnologie implementieren können. Heute werde ich die fünf wichtigsten Skalierbarkeitsmuster hervorheben, die dafür sorgen, dass Apps und das Internet rund um die Uhr online und verfügbar bleiben.

Globaler Server-Lastausgleich (GSLB)

GSLB ist ein völlig falscher Name. Dabei ging es nie wirklich um den Lastausgleich der Server , sondern um die Site- Verfügbarkeit. Heute gilt dies auch für die Verfügbarkeit von Apps.

Mit GSLB stellen Sie sicher, dass Sie ein anderes Rechenzentrum (Cloud oder herkömmliches Rechenzentrum) finden, wenn es nicht reagiert. GSLB kann auf Domänen- oder Hostebene angewendet werden. Sie können es also verwenden, um example.com sowie api.example.com zwischen Standorten zu wechseln.

In seiner einfachsten Form verwendet GSLB eine rudimentäre, DNS-basierte Lastverteilung. Das heißt, es verfügt über eine Liste von IP-Adressen, die mit einer Domäne oder einem Host verknüpft sind. Wenn die erste nicht verfügbar ist, werden Anfragen an die zweite in der Liste weitergeleitet – oder an die dritte oder vierte usw.

Dieser Vorgang besteht aus zwei Schritten:

  1. Fragen Sie den globalen Load Balancer nach der entsprechenden IP-Adresse. Dies ist der negative Aspekt, der immer mit GSLB in Verbindung gebracht wird: Wenn Sie in den letzten 15 Minuten oder dem aktuellen TTL-Wert nach der IP-Adresse von cheese.com gefragt haben, erhalten Sie die letzte Antwort, die Sie erhalten haben. Wenn die Site in dieser Zeit ausfällt, können Sie keine Verbindung herstellen.
  2. Senden Sie die Anfrage an die IP-Adresse der Site, die von der GSLB-Anfrage zurückgegeben wurde. Dabei handelt es sich häufig um einen lokalen Lastenausgleich, der seine eigenen Algorithmen und Entscheidungsprozesse verwendet, um die Anforderung an die entsprechende Ressource weiterzuleiten.

Die Entscheidung aus Schritt 1 beruht im Allgemeinen nicht auf Informationen, sondern ausschließlich darauf, ob eine bestimmte Site reagiert oder nicht. Dennoch können Sie auf diese Weise mehrere Standorte (Cloud, Hosting-Anbieter, vor Ort) nutzen, um die Verfügbarkeit sicherzustellen. Durch die strategische Auswahl von Standorten in unterschiedlichen geografischen Gebieten können Sie die Auswirkungen von Naturkatastrophen oder Internetausfällen vermeiden.

Aber das ist eher ein DR- (Disaster Recovery) oder BC- (Business Continuity) Szenario. Andere nutzen die Vorteile intelligenterer GSLB-Anwendungsdienste wie Geolokalisierung und Anwendungsleistung. Wenn also die App auf Site A eine schlechte Leistung zeigt, möchten Sie die Besucher vielleicht auf Site B weiterleiten, bis das Problem behoben ist. Oder Sie möchten Benutzer möglicherweise zum geografisch nächstgelegenen Standort weiterleiten, um die Leistung zu verbessern (da die Lichtgeschwindigkeit immer noch eine Regel ist und die Entfernung für die App-Leistung eine Rolle spielt).

Unabhängig davon, wie die Entscheidung getroffen wird, bleibt das Grundmuster dasselbe: GLSB verteilt Anfragen auf mehrere, physisch getrennte Standorte, indem es die IP-Adresse eines der verfügbaren Standorte zurückgibt. Ob APIs oder Apps, GSLB ist ein Muster zur Verfügbarkeitssicherung auf höchster Ebene.  

Einfaches altes Lastenausgleichssystem (POLB)

Verbindungsbasierte Verfügbarkeit

„Plain Old Load Balancing“ (POLB) ist ein Begriff, den ich gerne verwende, um standardmäßiges, TCP-basiertes Lastenausgleich zu beschreiben. Mit diesem Muster wird Verfügbarkeit einfach dadurch erreicht, dass Apps geklont werden und sichergestellt wird, dass eine Verbindung zwischen dem Client (Benutzer, Gerät) und der App hergestellt werden kann.

Der Load Balancer (oder Proxy, wenn Sie das bevorzugen) empfängt eine Verbindungsanforderung, wählt eine verfügbare App-Instanz aus und leitet die Verbindung weiter. Dies ist das letzte Mal, dass der Load Balancer aktiv eingreift. Es ist wie die „Einführungs-E-Mail“, mit der Sie das Treffen zweier Kollegen erleichtern. Sie nehmen aktiv am ersten Austausch teil, werden anschließend jedoch in die CC-Zeile verschoben und beteiligen sich im Allgemeinen nicht weiter.

Ich verwende den Begriff POLB, weil bei der Entscheidung, wie Anfragen weitergeleitet werden, lediglich Algorithmen eine Rolle spielen. Leider kann je nach dem zum Verteilen der Anfragen verwendeten Algorithmus eine Menge schiefgehen. Beim Round Robin-Verfahren werden beispielsweise Kapazität und Leistung nicht berücksichtigt. Es wird einfach „die nächste App“ ausgewählt und die Anfrage wird abgeschickt. Die Auswahl der Option „geringste Verbindungen“ kann sich durch das Laden einer Ressource schnell auf die Leistung auswirken, während andere möglicherweise schneller sind. Die Auswahl der Algorithmen wird zu einer kritischen Komponente für die Aufrechterhaltung der Verfügbarkeit.

POLB ist die Standardmethode zum Lastenausgleich in Containerumgebungen und für viele Cloud-native Lastenausgleichsdienste.

Persistenz

Sticky Sessions und SSL

Eine der Realitäten dreischichtiger Anwendungen besteht darin, dass sie in der Regel zustandsbehaftet sind. Das heißt, sie speichern zwischen Anfragen und Antworten Informationen, die für den Betrieb der Anwendung entscheidend sind. Ihr Einkaufswagen, Ihre Anmeldeinformationen, Ihr Status, die zuletzt besuchte Seite und der aktuelle Schritt eines Prozesses sind alles Informationen, die oft als Teil der „Sitzung“ gespeichert werden. Das Problem ist, dass viele Apps, die mit Drei-Schichten-Frameworks entwickelt wurden, diese Sitzung letztendlich auf dem Anwendungs- oder Webserver und nicht in einer Datenbank speicherten. Das bedeutete, dass Sie, sobald Sie mit einem Server verbunden waren, immer wieder zu diesem Server zurückkehren mussten, um sicherzustellen, dass alle Ihre Informationen verfügbar waren.

Lastenausgleichsmodule implementieren Persistenz auf verschiedene Arten, die beliebteste ist die Cookie-basierte. Sitzungs-IDs wurden in einem Cookie gespeichert und dann vom Lastenausgleich verwendet, um sicherzustellen, dass die Anfragen an den richtigen Server gingen, wodurch ein algorithmischer Auswahlprozess effektiv umgangen wurde.

Als die Verwendung von SSL/TLS zu einer entscheidenden Voraussetzung für das Sicherheitsgefühl der Käufer wurde, traten dieselben Probleme erneut auf. SSL/TLS ermöglicht eine sichere Sitzung zwischen einem Client und einem bestimmten App-Server. Um sicherzustellen, dass beide Seiten der Konversation die über diese Verbindung ausgetauschten Daten entschlüsseln und verwenden konnten, musste der Load Balancer in der Lage sein, Client-Anfragen an denselben Server zu senden, auf dem er gestartet war. Durch die Verwendung derselben Techniken, die die sitzungsbasierte Persistenz ermöglichen, konnten Load Balancer die SSL/TLS-basierte Persistenz unterstützen.

Unabhängig von der konkreten Art der verwendeten Persistenz ist das Muster dasselbe. Wenn es einen Hinweis darauf gibt, dass bereits eine Sitzung hergestellt wurde, berücksichtigt der Load Balancer die bestehende Verbindung und stellt sicher, dass sie für die Dauer der Benutzersitzung bestehen bleibt. Wenn dies nicht der Fall ist, wählt der Load Balancer eine Ressource basierend auf ihrer Konfiguration und ihren Algorithmen aus und stellt die Verbindung her.

Dies hat Auswirkungen auf die Kapazitätsplanung bei der Auswahl eines Lastausgleichsalgorithmus. Für dieses Szenario ist die Option „Least Connections“ eine gute Wahl, da hierdurch sichergestellt wird, dass keine einzelne Ressource durch laufende Sitzungen überlastet wird, während andere ungenutzt herumliegen. Bei anderen Algorithmen besteht die Wahrscheinlichkeit, dass eine einzelne Ressource viele Benutzersitzungen gleichzeitig verwaltet, was sich negativ auf die Leistung für alle auf diesen Server umgeleiteten Benutzer auswirkt.

Hostbasierter Lastenausgleich

Virtuelle Server

Hostbasierter Lastenausgleich ist eines der gängigsten und am weitesten verbreiteten Skalierbarkeitsmuster. Sie denken vielleicht, dass Sie zur Implementierung keinen Load Balancer benötigen, da alle Webserver die Möglichkeit unterstützen, sich gleichzeitig als mehrere Hosts auszugeben. Aber das tust du. Obwohl ein Web-/App-Server mehrere virtuelle Server hosten kann, erfolgt nicht unbedingt ein Lastenausgleich zwischen ihnen. Sie benötigen also weiterhin einen Load Balancer zur Skalierung. Die Frage ist, ob der Load Balancer Hosts aufteilt oder ob Sie das dem Web-/App-Server überlassen.

Unabhängig davon, ob Sie Web-/App-Serveranweisungen oder einen externen Lastenausgleich verwenden, bleibt der Ablauf derselbe. Eine Anforderung wird gestellt und vom Ziel (Load Balancer oder Web-/App-Server) empfangen. Der Zielserver überprüft dann die HTTP-Header und findet den Hostwert, bevor er die Anfrage an den entsprechenden virtuellen Server weiterleitet. 

Der Vorteil der Verwendung eines Load Balancers zum Aufteilen von Hosts liegt in der Fähigkeit, Domänen basierend auf dem Host zu isolieren und sie einzeln zu skalieren. Dies ist effizienter und kann die Anzahl der Server (Hardware und Software) reduzieren, die Sie zum Skalieren einer Anwendung benötigen. Darüber hinaus wird die Kapazitätsplanung vereinfacht, da Sie besser vorhersagen können, welche Last jeder Hostserver zu einem bestimmten Zeitpunkt bewältigen kann.

Dies liegt daran, dass das Aufrufen der Geschäftslogik hinsichtlich des erforderlichen Rechenaufwands nicht dasselbe ist wie das Anfordern eines Bildes. Das Mischen und Anpassen von Hosts in derselben Skalierbarkeitsdomäne führt zu volatiler Last und unvorhersehbarer Kapazität. Wenn Sie sich für die Verwendung eines Lastenausgleichs zum einfachen Lastenausgleich entscheiden, ist der Web-/App-Server dafür verantwortlich, Hosts aufzuteilen und Anforderungen an den entsprechenden virtuellen Server weiterzuleiten. Ein weiterer Nachteil dieses Ansatzes liegt darin, dass die Infrastruktur gemeinsam genutzt wird und es aufgrund von Versionskonflikten und Patches sowie App-Updates zu Reibungen zwischen virtuellen Servern kommen kann.

Die zunehmende Nutzung von Containern und Mikroservices treibt den Einsatz hostbasierter Lastverteilung in Form von Ingress-Controllern voran.

Strecke und Rückfahrt 

Lastenausgleich auf Schicht 7 (HTTP)

Aufgrund der Vielseitigkeit (Agilität?), die es bietet, ist mir die Lastverteilung auf Layer 7 (HTTP) am liebsten. Sie können Anfragen auf der Grundlage von HTTP-Inhalten ausgleichen, einschließlich der Nutzlast. Die meisten Leute beschränken (meiner Meinung nach klugerweise) ihre Lastausgleichsregeln auf das, was im HTTP-Header gefunden werden kann. Dazu gehören unter anderem der Host, die HTTP-Methode, der Inhaltstyp, Cookies, benutzerdefinierte Header und der User-Agent.

Beim HTTP-Lastausgleich geht es zuerst um das Routing und dann um den Lastausgleich. Ein typisches HTTP-Lastausgleichsmuster hat die Form Route –> Verteilen. Das bedeutet, dass zunächst entschieden wird, an welchen virtuellen Server eine Anfrage gerichtet werden soll und anschließend ein Algorithmus eine Ressource aus dem Pool auswählt, der diesen virtuellen Server unterstützt.

Der HTTP-Lastausgleich ermöglicht Muster wie die API-Versionierung, bei der die API-Version in die URI (oder in einen benutzerdefinierten HTTP-Header) eingebettet ist. Der Load Balancer kann Versionen trennen und sicherstellen, dass Clients zur Ausführung an den richtigen Back-End-Dienst gesendet werden. Dies ermöglicht stets eine reibungslose Migration von Clients in Situationen, in denen Sie kein Upgrade erzwingen können.

Diese Art von Skalierbarkeitsmuster unterstützt auch andere Skalierbarkeitsmuster wie funktionale Zerlegung und Datenpartitionierung. Es handelt sich dabei um das robusteste und agilste Skalierbarkeitsmuster im Mix und ermöglicht eine breite Palette an Optionen für die Skalierung von Apps und zunehmend auch von Microservices.

Zusammenfassend gibt es also fünf große Skalierbarkeitsmuster, von denen die meisten kombiniert werden können (und oft auch werden), um eine möglichst effiziente Ressourcennutzung und die größtmögliche Leistung zu ermöglichen. Wenn Sie derzeit noch keine davon verwenden, werden Sie das wahrscheinlich bald tun. Daher ist das Verständnis ihrer grundlegenden Zusammensetzung eine gute Basis für den Aufbau einer skalierbaren Architektur, unabhängig davon, welche Art von Apps Sie verwenden oder wo Sie diese bereitstellen.

Skalieren Sie weiter!