Beim Skalieren von Apps und APIs geht es heutzutage nicht mehr um die Wahl des richtigen Lastausgleichsalgorithmus. In den mehr als zwei Jahrzehnten der Entwicklung der App-Bereitstellung ist eines ziemlich konstant geblieben: die Algorithmen zum Lastausgleich. Ihr Hauptnutzen liegt in der Aufrechterhaltung der Verfügbarkeit. Ihr Einfluss auf die Leistung ist bestenfalls minimal.
Dies bedeutet nicht, dass die Wahl eines Algorithmus irrelevant sei. Schließlich ist Round Robin selten die beste Wahl für eine API oder Anwendung, aber die Entscheidung zwischen den wenigsten Verbindungen und der schnellsten Reaktion wirkt sich wahrscheinlich weniger auf die Gesamtleistung und Verfügbarkeit eines digitalen Dienstes aus als seine Architektur.
Dabei handelt es sich um eine architektonische Perspektive auf die App-Bereitstellung als Reaktion auf die Aufwertung der App-Bereitstellung als eine der sechs Schlüsselfähigkeiten, die für die Entwicklung und den Betrieb digitaler Dienste erforderlich sind.
Ein Lastausgleichsalgorithmus ist ein programmgesteuerter Ansatz zum Verteilen der Last auf einen Ressourcenpool, um die Verfügbarkeit sicherzustellen und die Leistung zu verbessern.
Ein Lastausgleichsalgorithmus gibt an, wie bestimmte Ressourcen ausgewählt und welche Variablen berücksichtigt werden.
Round Robin ist der einfachste Algorithmus und iteriert einfach in sequenzieller Reihenfolge über einen bekannten Satz von Ressourcen. Wenn drei Ressourcen vorhanden sind – A, B und C – wird die erste Anforderung im Round-Robin-Verfahren an A, die zweite an B und die dritte an C weitergeleitet. Anschließend beginnt der Auswahlvorgang erneut.
Least Connections ist ein Algorithmus, der auf dem zweiten operationellen Axiom basiert, das besagt, dass „mit zunehmender Belastung die Leistung abnimmt“. Der Algorithmus mit den wenigsten Verbindungen wählt die Ressource mit den wenigsten Verbindungen (Last). Es gibt Variationen dieses Algorithmus, insbesondere den Algorithmus „Gewichtete geringste Verbindungen“ , der Kapazitätsunterschiede zwischen Ressourcen berücksichtigt.
Die schnellste Reaktionszeit wird verwendet, wenn die Leistung oberste Priorität hat. Der Load Balancer ermittelt entweder passiv oder aktiv die Antwortzeit jeder Ressource und wählt für jede Anforderung die schnellste aus. Dieser Algorithmus garantiert keine Benutzerantwortzeit , da er keinen Einfluss auf die letzte Meile oder die Benutzernetzwerkbedingungen hat.
Die Quell-IP ist ein Algorithmus, der aus dem Netzwerklastenausgleich übrig geblieben ist und zur Auswahl einer Ressource einen einfachen Hashwert für die Quell-(Client-)IP verwendet. Dieser Algorithmus wählt für eine bestimmte Quell-IP immer dieselbe Ressource aus. Dieser Algorithmus geriet in Ungnade, da er dem „Mega-Proxy“-Problem unterliegt, bei dem alle Benutzer, die von einem einzigen Proxy/einer einzigen IP-Adresse stammen, auf dieselbe Ressource umgeleitet werden. Dadurch wird die Zielressource tendenziell überlastet, was zu schlechter Leistung und letztendlich zum Ausfall führt.
Lastausgleichsalgorithmen sind ein wichtiger Teil einer App-Bereitstellungsarchitektur, haben jedoch einen geringeren Einfluss auf die Leistung und Skalierbarkeit einer App oder eines digitalen Dienstes als der allgemeine Architekturansatz.
Unter App-Bereitstellung versteht man die Entwicklung einer skalierbaren, leistungsstarken Architektur für Apps, APIs und digitale Dienste. Es stützt sich in hohem Maße auf den Lastenausgleich als Kernkomponente, integriert jedoch auch moderne Funktionen wie Layer-7-Routing und nutzt gängige Architekturmuster, um die Leistung zu optimieren und die Ressourcen effizient zu nutzen.
Wir verwenden den Begriff „App-Bereitstellung“, um bewusst eine Grenze zwischen Lastausgleich, einem Implementierungsdetail, und Architektur, einem Entwurfsprozess, zu ziehen.
Skalierung ist die technische Reaktion auf ein Geschäftsergebnis. Nämlich die Notwendigkeit, die Verfügbarkeit und Leistung der Workloads, aus denen ein digitaler Dienst besteht, aufrechtzuerhalten, um die Kundenzufriedenheitswerte, die Konversionsraten und die Umsatzgenerierung zu verbessern. Dieser letzte Teil ist besonders wichtig, da unsere Untersuchungen ergeben haben, dass die Mehrheit (58 %) der Unternehmen heute mindestens die Hälfte ihres Umsatzes mit digitalen Diensten erzielt.
Denken Sie beispielsweise auch an die Nutzung der öffentlichen Cloud zur Geschäftskontinuität (BC). BC ist eine der wichtigsten Hauptanwendungsbereiche der öffentlichen Cloud und besteht im Kern aus einer Implementierung auf globaler Ebene, d. h. einem globalen Lastenausgleich. Failover ist eine Kernfunktion der App-Bereitstellung, die, wenn sie auf eine ganze Site angewendet wird, die Möglichkeit bietet, Anfragen schnell von einem Standort zu einem anderen umzuleiten. Die kontinuierliche Verfügbarkeit der digitalen Präsenz eines Unternehmens ist ein Geschäftsergebnis, das durch eine technische Reaktion ermöglicht wird.
Mit der Beantwortung dieser Frage beginnt unsere technische Reise in die App-Bereitstellungsarchitektur. Es gibt zwei Skalierungsmodelle: vertikal (nach oben) und horizontal (nach außen).
Die vertikale Skalierung basiert auf dem Prinzip, dass die Kapazität eines Systems durch Hinzufügen weiterer Verarbeitungsleistung erhöht wird. Von dieser Skalierungsmethode profitieren vor allem monolithische Anwendungen und Systeme, die in sich geschlossen sind. Abgesehen von der Infrastruktur verlassen sich die meisten Organisationen nicht mehr auf die vertikale Skalierung, da hierfür eine Änderung der physischen Umgebung erforderlich ist – beispielsweise das Hinzufügen von CPUs oder RAM oder die Erweiterung der Netzwerkkapazität. Während die vertikale Skalierung durch Virtualisierung, insbesondere in öffentlichen Cloud-Umgebungen, viel schneller erfolgt, kann die erforderliche Migration von Software und Systemen – selbst auf eine neue virtuelle Maschine – zu Störungen führen.
Horizontale Skalierung ist ein architektonischer Ansatz zur Bereitstellung von mehr Verarbeitungsleistung durch Erhöhung der insgesamt verfügbaren Ressourcen. Dies wird durch die Verteilung der Verarbeitungsleistung auf mehrere Instanzen einer Anwendung, eines Dienstes oder eines Systems erreicht. Dies ist heutzutage die gängigste Skalierungsmethode, da sie auf der Duplizierung von Ressourcen statt auf ihrer Migration basiert. Darüber hinaus bietet die horizontale Skalierung eine größere Vielfalt an Architekturoptionen als die vertikale Skalierung und ist daher für alle Anwendungen und APIs besser geeignet.
Es dürfte daher keine Überraschung sein, dass moderne App-Bereitstellungsmuster auf dem Prinzip der horizontalen Skalierung basieren.
Mit der bloßen Auswahl des horizontalen Maßstabs ist die Diskussion nicht beendet.
Sobald die Entscheidung gefallen ist (im Allgemeinen ist dies die Standardentscheidung), sollten zusätzliche Überlegungen in die Architekturentscheidung bezüglich der Implementierung einfließen. Am einfachsten lässt sich diese Entscheidung durch die Linse des Skalenwürfels angehen, wie er im Buch „The Art of Scalability“ beschrieben wird.
Ganz einfach: Der Maßstabwürfel hat drei Achsen: x, y und z. Jedes davon entspricht einem Architekturmuster für den Lastausgleich. Jedes dieser Muster ist zum Erreichen spezifischer Ergebnisse in Bezug auf Leistung und Verfügbarkeit bei unterschiedlichen Arten von Anwendungen und APIs geeignet.
Ein digitaler Dienst verwendet wahrscheinlich eine Architektur, die mehrere Muster enthält, um Leistung und Ressourcenverbrauch gleichzeitig zu optimieren. Dieser Ansatz erfordert systemisches Denken, da alle Komponenten, ihre Interaktion und der Anforderungsfluss vom Benutzer zur App und zurück berücksichtigt werden müssen.
Das X-Achsen-Muster ist das grundlegendste Muster. Es basiert auf horizontaler Duplizierung und der Großteil der Arbeit wird über einen Lastausgleichsalgorithmus erledigt. Es ist das einfachste Muster und führt zu dem, was ich Plain Old Load Balancing (POLB) nenne.
Wir nennen es so, weil die Architektur so einfach ist und die erweiterten Funktionen moderner Load Balancer zur Interaktion mit Anfragen und Antworten auf der Anwendungsebene nicht nutzt.
In diesem Muster werden Anwendungen dupliziert und Anforderungen basierend auf der Entscheidung des konfigurierten Lastausgleichsalgorithmus an eine Instanz weitergeleitet.
Da dieses Muster häufig in Verbindung mit TCP (Schicht 4) verwendet wird, bietet es Leistungsvorteile gegenüber anderen Mustern, die auf der Überprüfung von HTTP (Schicht 7) basieren. Verbindungen können hauptsächlich zusammengefügt und nicht über einen Proxy geleitet werden, wodurch der Load Balancer nach der ersten Verbindung effektiv zu einem Netzwerk-Hop wird. Dies führt insgesamt zu einer besseren Leistung, verhindert jedoch, dass der Load Balancer nach der ersten Verbindung Anfragen und Antworten prüfen oder darauf reagieren kann. Da X-Achsen-Architekturen eine hervorragende Verfügbarkeit gewährleisten und eine hohe Leistung aufweisen können, werden sie häufig zum Skalieren von Infrastruktur- und Sicherheitsdiensten wie Firewalls und Anwendungs-Gateways verwendet.
Zahlreiche herkömmliche Anwendungen (Monolithen, dreistufiges Web und Client-Server-Anwendungen) werden tendenziell mit diesem Muster skaliert, da diese Anwendungen nur selten in diskretere Komponenten zerlegt werden, die für moderne App-Bereitstellungsarchitekturen genutzt werden können.
Dieses Muster basiert auf funktionaler Zerlegung und nutzt die Funktionen der Anwendungsschicht (Schicht 7) der App-Bereitstellung, um eine Skalierung basierend auf Funktionen statt auf ganzen Systemen zu ermöglichen. Das Y-Achsen-Muster ist das erste Muster, bei dem Layer-7-Routing zu einem wichtigen Werkzeug im Werkzeugkasten der App-Delivery-Architektur wird.
Im Allgemeinen nutzen y- und z-basierte Muster das Layer-7-Routing, um einen Pool auszuwählen. Anschließend wird ein Lastausgleichsalgorithmus verwendet, um eine bestimmte Ressource auszuwählen. Dies weicht vom grundlegenden X-Muster ab, bei dem kein Layer-7-Routing verwendet wird.
Dieses Muster geht von einem Betrieb auf Ebene 7 (normalerweise HTTP) aus und verwendet einige Variablen, um den Datenverkehr auf bestimmte Instanzen einer Anwendung oder eines Dienstes zu verteilen. Wenn beispielsweise das Muster /login in der URI gefunden wird, wählt der Load Balancer basierend auf dem konfigurierten Lastausgleichsalgorithmus eine Instanz aus einem Pool von App-Instanzen aus, die nur Anmeldeanforderungen verarbeiten. Die Variable kann ein beliebiger Bestandteil des Anforderungsheaders oder der Nutzlast der Anforderung sein. Dies ermöglicht agentenbasiertes Routing, API-Routing und inhaltsbasiertes Routing (Bilder, Skripte usw.).
Anwendungsinstanzen können Klone sein. Dies ist häufig der Fall, wenn es Unterschiede bei der Nutzung einer App gibt, die durch eine Variable in der Anfrage identifiziert werden können. Beispielsweise Login- versus Checkout -Funktionen kann in einer Anfrage anhand der URI, eines Wertes im HTTP-Header oder eines Wertes in der Anfragenutzlast erkannt werden. Durch die Anwendung eines Y-Achsen-Musters können herkömmliche Anwendungen funktionsbasiert skaliert werden. Dies führt zu einer effizienteren Ressourcennutzung, da mehr Ressourcen für die Handhabung umfangreicher Funktionen zugewiesen werden können, während die erwartete Leistung anderer Funktionen aufrechterhalten wird.
Die Verwendung des Y-Achsen-Musters zur funktionalen Skalierung herkömmlicher Anwendungen entstand vor der Verbreitung von Microservices, die Anwendungen heute funktional zerlegen. Das Y-Achsen-Muster ist immer noch auf Microservices anwendbar und wird heute tatsächlich von Ingress-Controllern implementiert. Aufmerksame Leser werden bemerken, dass dieses Muster auch auf APIs anwendbar ist, da sie auf HTTP-Konstrukten (Schicht 7) basieren. Daher ist es keine Überraschung, dass API-Gateways dieses grundlegende Muster nutzen.
Dieses Muster wurde in den frühen Tagen des Web 2.0 durch eBay populär gemacht . Seine Skalierbarkeitsarchitektur umfasste dann die Segmentierung von Funktionen in separate Anwendungspools. Die Verkaufsfunktionalität wurde von einem Satz Anwendungsserver bereitgestellt, die Gebotsfunktion von einem anderen, die Suchfunktion von noch einem weiteren. Insgesamt organisierten sie rund 16.000 Anwendungsserver in 220 verschiedenen Pools. Dadurch konnten sie jeden Pool unabhängig voneinander skalieren, entsprechend den Anforderungen und dem Ressourcenverbrauch seiner Funktion. Darüber hinaus konnten sie Ressourcenabhängigkeiten isolieren und rationalisieren – der Verkaufspool musste beispielsweise nur mit einer relativ kleinen Teilmenge der Backend-Ressourcen kommunizieren.
Das Muster der Y-Achse kann auch verwendet werden, um verschiedene Arten von Inhaltsanforderungen, wie etwa Bilder, an einen Ressourcenpool und andere Inhaltstypen an andere zu verteilen.
Durch die Lastverteilung über die Y-Achse können die Komponenten eines digitalen Dienstes individuell skaliert werden, was im Hinblick auf die Ressourcennutzung weitaus effizienter ist als ein Muster über die X-Achse. Es ermöglicht eine Konfigurationsoptimierung auf der Service- oder Anwendungsebene, die die Leistung durch die Anpassung bestimmter Variablen im Web- oder App-Server zur Optimierung für einen bestimmten Inhaltstyp verbessern kann.
Das Z-Achsen-Muster wurde aus purer Notwendigkeit heraus mit dem explosiven Wachstum der sozialen Medien und des Internets im Allgemeinen populär. Im Kern handelt es sich um ein Skalierungsmuster für die Y-Achse mit zusätzlicher Segmentierung, die normalerweise auf einer bestimmten Variablen wie einem Benutzernamen oder einer Gerätekennung basiert.
Dieses Muster ermöglicht eine architektonische Differenzierung mithilfe einer aus der Datensplitterung abgeleiteten Technik.
Dieses Muster wendet die in Datenbanken verwendeten Prinzipien an, um Anfragen basierend auf bestimmten Datenteilen in der Anfrage zu verteilen. Es kann zum Beheben von Engpässen in der Datenebene sowie zur Gewährleistung der Einhaltung von Regeln zur Datensouveränität eingesetzt werden. Es verwendet eine identifizierbare – und normalerweise eindeutige – Variable, um Anfragen über einen horizontal skalierten Ressourcenpool weiterzuleiten. Dieses Muster wird im Allgemeinen verwendet, wenn ein hoher Durchsatz erforderlich ist, z. B. bei einer großen Anzahl von Anfragen für einen bestimmten Dienst oder eine bestimmte Anwendung.
Das Z-Achsen-Muster ist besonders nützlich für die Verwaltung von Edge- und IoT-Geräten, deren Anzahl in die Millionen gehen kann. Durch die Verwendung von Gerätekennungen als Basismuster für Sharding-Anfragen kann die Geschwindigkeit, mit der Datenübertragungen durchgeführt werden können, erheblich verbessert werden. Dies kann insbesondere für Geräte hilfreich sein, die ihre Konfigurationen an einem Remote-Standort (Cloud oder Rechenzentrum) speichern, da diese Daten für das Gerät eindeutig sind und sicher aufgeteilt werden können.
Dieses Muster verbessert tendenziell die Leistung, da der Datenzugriff bei hoher Last die Leistung erheblich beeinträchtigen kann. Durch die Aufteilung des Datenzugriffs auf mehrere Instanzen wird die Belastung verringert und damit auch die Leistung verbessert. Dabei ist sorgfältige Beachtung der Datenintegrität erforderlich, und beim Sharding gemeinsam genutzter Daten kann es zu Konsistenzproblemen kommen. Meta hat das Thema Sharding auf eine höhere Ebene gebracht , als es Service-Sharding als Teil seiner Gesamtarchitektur entwickelte. Die sorgfältige Entwicklung einer hochleistungsfähigen und skalierbaren App-Bereitstellungsarchitektur ist ein hervorragendes Beispiel dafür, wie die Anerkennung der App-Bereitstellung als formale Ebene innerhalb einer größeren Architektur erhebliche Vorteile bringen kann.
Bei Diensten, die auf nicht primäre Datenquellen zugreifen, kann ein Z-Achsen-Muster den Durchsatz verbessern, ohne die Datenqualität im gesamten System wesentlich zu beeinträchtigen. Bei diesem Ansatz ist es nicht mehr nötig, Code hinzuzufügen, um eine bestimmte Instanz einer Anwendung oder API an eine Datenquelle zu binden. Stattdessen wird durch eine Kombination aus der Konfiguration der Datenkonnektoren auf Instanzebene und der App-Bereitstellungsweiterleitung sichergestellt, dass die richtige Datenquelle verwendet wird.
In einer Welt, in der digitale Dienste bereitgestellt werden, kommt es heutzutage nur noch selten vor, dass für die Entwicklung eines leistungsstarken und zuverlässigen digitalen Dienstes nur ein einziges App-Bereitstellungsmuster verwendet wird. Der Grund hierfür liegt in der inhärenten Komplexität digitaler Dienste und der zunehmenden Vielfalt der „Benutzer“ – die sich über Geräte, Menschen und Software erstrecken kann.
Ein architektonischer Ansatz berücksichtigt daher die bestmögliche Nutzung von App-Bereitstellungsmustern über einen digitalen Dienst hinweg, um den Benutzern ein optimales Erlebnis zu bieten.
Es gibt keine „richtige“ oder „falsche“ Architekturlösung, da diese in hohem Maße von den Diensten und Anwendungen abhängt, aus denen ein digitaler Dienst besteht. Eine solche Lösung sollte jedoch nicht ausschließlich auf Lastausgleichsalgorithmen basieren.
Man sollte allerdings beachten, dass die Algorithmusauswahl nicht erwähnt wurde, da die Wahl der Lastverteilung innerhalb eines Lastausgleichsmusters nicht so relevant ist wie die Wahl der richtigen Architektur für eine bestimmte App oder API.
Dies ist einer der Faktoren, die die App-Bereitstellung als Disziplin vorantreiben . Die Art und Weise, wie App-Bereitstellung und -Sicherheit heutzutage genutzt und implementiert werden, geht weit über die einfache Größenordnung eines Webservers hinaus. Die Implementierung kann sich auf die Leistung und Verfügbarkeit auswirken und letztlich über den Erfolg oder Misserfolg des Unternehmens entscheiden. Daher ist es für Unternehmen wichtig, die App-Bereitstellung als strategisches, architektonisches Werkzeug in ihrem Design-Werkzeugkasten zu betrachten.
Der Lastenausgleich bleibt die wichtigste technische Voraussetzung für die Skalierung. Wenn man die Bereitstellungsmuster von Apps und ihre Nutzung des Lastenausgleichs versteht, erhält man eine bessere Perspektive bei der Architekturgestaltung hinsichtlich Skalierbarkeit und Leistung digitaler Dienste, insbesondere dann, wenn diese Dienste vermutlich hybrid sind und aus einer Mischung von APIs sowie modernen und herkömmlichen Apps bestehen.