Was ist eine typische Methode zum Skalieren eines Software Load Balancers?

22

Ich sehe oft Web-App-Architekturen mit einem SLB / Reverse-Proxy vor einer Reihe von App-Servern.

Was passiert, wenn die Anzahl der Verbindungen zum SLB zu viele Ressourcen erfordert, um von einem einzelnen SLB effektiv verarbeitet zu werden? Betrachten Sie für ein konkretes, aber übertriebenes Beispiel 2 Millionen dauerhafte HTTP-Verbindungen. Offensichtlich kann ein einzelner SLB damit nicht umgehen.

Was ist die empfohlene Konfiguration für die Skalierung aus einer SLB?

Ist es typisch, eine Gruppe / einen Cluster von LBs zu erstellen? Wenn ja, wie verteilt sich die Clientlast auf die Gruppe der LBs?

z8000
quelle
z8000, Können Sie sagen, welche Software zum Lastenausgleich Sie verwenden? Außerdem, wenn möglich, welcher Algorithmus / welches Protokoll zum Lastenausgleich verwendet wird.
Martin
Ich habe keine Präferenz. Ich habe die Frage aktualisiert, um sie klarer zu machen.
z8000
Mir ist nicht klar, warum ein Load Balancer grundsätzlich nicht mit 2 Millionen dauerhaften HTTP-Verbindungen umgehen kann.
womble

Antworten:

10

Lastverteiler können nicht einfach von anderen Lastverteilern skaliert werden, da in der Kette inhärent ein einzelner Lastverteiler vorhanden ist, der die Verbindungen aufrechterhält. Trotzdem haben Balancer wie LVS oder HAProxy eine absurde Kapazität im Gbit / s-Bereich. Sobald Sie die Möglichkeiten eines einzelnen Load Balancers (Software, Hardware usw.) überschritten haben, müssen Sie sich mit anderen Techniken wie Round-Robin-DNS befassen.

Hyppy
quelle
Recht! Die Single LB zu haben ist das "Problem". Ich bin damit einverstanden, dass der Durchsatz im Allgemeinen kein Problem darstellt. Aber ich mache mir Sorgen um andere Ressourcen wie RAM, die in meinem Fall begrenzt sind. Es gibt nur so viele Verbindungen, die auf einem einzigen SLB gehostet werden können, bevor der RAM-Speicher voll ist.
z8000
HAProxy kann ungefähr 20.000 bis 60.000 aktive Sitzungen pro GB RAM verarbeiten. Ich glaube, LVS kann viel mehr, da die gespeicherten Sitzungsdaten kleiner sind. Wenn Ihnen der Arbeitsspeicher ausgeht, aktualisieren Sie ihn oder erstellen Sie einen anderen Lastenausgleich, der von einem Round-Robin-DNS-System unterstützt wird.
Hyppy
1
"Lastverteiler können nicht einfach von anderen Lastverteilern skaliert werden" - tatsächlich kann ein einzelner ASIC-basierter L4-Lastverteiler häufig mit hervorragenden Ergebnissen vor ein paar L7-HTTP-basierten Lastverteilern platziert werden. Das gleiche Grundprinzip gilt für reine Software-Implementierungen, zum Beispiel Linux LVS vor nignx.
Jesper M
19

OK, gibt es bereits eine akzeptierte Antwort, aber es ist etwas hinzuzufügen .. Die ‚klassische‘ Wege am häufigsten von dem Load - Balancer - Tiere Skalierung sind (in keiner bestimmten Reihenfolge):

  • DNS Round Robin zur Veröffentlichung mehrerer IP-Adressen für die Domain. Implementieren Sie für jede IP-Adresse ein hochverfügbares Serverpaar (2 Server, die zusammenarbeiten, um eine IP-Adresse zu gewährleisten). Jede IP-Adresse entspricht einem Load-Balancer-Cluster, entweder unter Verwendung von Appliances oder von Servern mit Load-Balancing-Software. Horizontale Skalierung durch Hinzufügen weiterer Load-Balancer-Paare nach Bedarf.

  • Routing- oder Firewall-Optimierungen verteilen die Last auf mehrere Load-Balancer. Lassen Sie den Front-Router oder die Front-Firewall die eingehenden Verbindungen auf mehrere IP-Adressen (die jeweils ein Load-Balancer-Paar darstellen) verteilen, indem Sie die Quell-IP-Adresse mit mehreren kostengünstigen Routen zu den Load-Balancern oder ähnlichem kombinieren.

  • Eine Schicht von Lastausgleichsmodulen auf IP-Ebene vor einer Schicht von Lastausgleichsmodulen auf HTTP-Ebene . Der IP-Layer-Lastausgleich kann in ASICs / Silizium implementiert werden und kann für einige Dinge schnell aufgehoben werden. Somit kann ein einzelnes IP-Load-Balancer-Paar häufig mit mehreren HTTP / HTTPS-Level-Load-Balancern mithalten und Multi-Gigabit-Performance-Levels bereitstellen, während die Architektur schön und einfach bleibt.

Um die verschiedenen oben genannten Möglichkeiten vollständig zu vertiefen, wäre eine sehr lange Antwort erforderlich. Im Allgemeinen ist es jedoch nicht so schwierig, die Lastausgleichsschicht zu skalieren , sondern die Anwendungsserverschicht und insbesondere die Datenbankschicht.

Es ist weniger wichtig, ob Sie einen Appliance-Formfaktor (F5, Cisco, A10) oder einen allgemeinen Server (Windows / Linux + -Software) auswählen. Die wichtigsten Überlegungen beim Skalieren der Lastausgleichsschicht sind:

  • State-full versus staatenlos. Brauchen Sie unbedingt Klebesitzungen oder können Sie ohne leben? Wenn man den Zustand nicht beibehält, wird alles einfacher.
  • "Hardware" (ASICs) versus "Software" (Allzweck-Server) für den Lastenausgleich. Jedes hat seine Vor- und Nachteile, siehe die oben verlinkte HAProxy-Übersichtsdokumentation.
  • L3 / 4-Lastausgleich (IP / TCP / IP) im Vergleich zu L7-Lastausgleich (HTTP) . Auch hier gibt das HAProxy-Dokument einen guten Überblick über die Vor- und Nachteile.
  • SSL-Terminierung , wo, auf den Webnodes oder auf dem Load Balancer.

Im Allgemeinen müssen Sie sich darüber keine Gedanken machen, bevor Ihre Website sehr groß wird - ein einziger moderner Server mit fx nginx verarbeitet Zehntausende einfacher HTTP-Anforderungen pro Sekunde. Tun Sie also keine vorzeitige Optimierung, beschäftigen Sie sich nicht damit, bevor Sie dazu gezwungen sind.

Jesper M
quelle
Es ist nicht unbedingt erforderlich, dass jede IP-Adresse mithilfe von DNS RR hoch verfügbar ist. Browser greifen im Allgemeinen auf eine andere IP-Adresse zurück, falls diese verfügbar ist, wenn sie keine Verbindung herstellen können. Wenn Sie jedoch über öffentliche Webdienste verfügen, benötigen Sie HA für jede IP-Adresse, da viele Webdienstbibliotheken das Failover auf andere IP-Adressen nicht automatisch verarbeiten.
Malayter
9

Der Schlüssel zum Skalieren einer HTTP-Lastausgleichsschicht besteht darin, zuerst eine weitere Schicht für den Lastausgleich auf niedrigerer Ebene (IP oder TCP) hinzuzufügen. Diese Schicht kann vollständig mit Open-Source-Software erstellt werden, obwohl Sie mit modernen Routern bessere Ergebnisse erzielen.

Die Flows (TCP-Sitzungen) sollten mithilfe von Headern wie Quell- / Ziel-IP- und TCP-Ports gehasht werden, um zu entscheiden, an welches Frontend sie gehen. Sie benötigen auch einen Mechanismus, der sicherstellt, dass ein Frontend nicht mehr verwendet wird, wenn es abstirbt.

Es gibt verschiedene Strategien. Ich werde ein paar skizzieren, die ich in der Produktion auf Websites für Millionen von Benutzern verwendet habe, damit Sie sich ein Bild machen können. Es wäre zu lang, um alles im Detail zu erklären, aber ich hoffe, diese Antwort gibt Ihnen genug Informationen / Hinweise, um loszulegen. Um diese Lösungen zu implementieren, benötigen Sie jemanden, der sich mit Netzwerken wirklich auskennt.

Zugegeben, was ich hier beschreibe, ist viel schwieriger zu implementieren als das, was in anderen Antworten beschrieben wird, aber dies ist wirklich der Stand der Technik, wenn Sie eine stark frequentierte Website mit großen Skalierbarkeitsproblemen und Verfügbarkeitsanforderungen von über 99,9% haben. . Vorausgesetzt, Sie haben bereits einen Netzwerktechniker an Bord, kostet das Einrichten und Ausführen (sowohl im Capex- als auch im Opex-Modus) weniger als Load-Balancer-Appliances, und es kann fast ohne zusätzliche Kosten weiter skaliert werden (im Vergleich zum Kauf eines neuen, sogar mehr) teures Gerät, wenn Sie aus Ihrem aktuellen Modell herauswachsen).

Erste Strategie: mit einer Firewall

Vermutlich haben Sie ein paar Router, an denen Ihre ISP-Uplinks angeschlossen sind. Ihr ISP bietet 2 Verbindungen (aktiv / passiv, mit VRRP). Auf Ihren Routern verwenden Sie auch VRRP und leiten den Datenverkehr in Ihrem öffentlichen Netzwerk an eine Firewall weiter. Die Firewalls ( FW 1und FW 2darunter) sind ebenfalls aktiv / passiv und filtern den Datenverkehr und senden jeden Datenfluss an einen funktionsfähigen Front-End-Server (Ihre HTTP-Load-Balancer FE 1und FE 2darunter).

      + -------------- + + -------------- +
      | ISP-Router A | | ISP-Router B |
      + -------------- + + -------------- +
             | |
           == # ====================== (öffentliches Netzwerk)
             | |
      + --------------- + + --------------- +
      | Ihr Router A | | Ihr Router B |
      + --------------- + + --------------- +
             | |
           == # ===== # ========= # ===== # == (RFC 1918 privates Netzwerk)
             | | | |
       + ------ + + ------ + + ------ + + ------ +
       | FW 1 | | FE 1 | | FE 2 | | FW 2 |
       + ------ + + ------ + + ------ + + ------ +

Das Ziel ist es, einen Fluss wie folgt aussehen zu lassen:

  1. Der ISP leitet den Datenverkehr zu Ihren IP-Adressen an Ihren aktiven Router weiter.
  2. Ihre Router leiten den Datenverkehr an einen VIP weiter, der eine RFC 1918- Adresse verwendet. Dieser VIP gehört der aktiven Firewall, ähnlich wie VRRP. Wenn Sie OpenBSD für Ihre Firewall-Anforderungen verwenden, können Sie CARP verwenden , eine patentfreie Alternative zu VRRP / HSRP.
  3. Ihre Firewall wendet den Filter an (z. B. "Nur 80 / TCP und 443 / TCP an diese bestimmte IP-Adresse zulassen").
  4. Ihre Firewall fungiert auch als Router und leitet die Pakete an ein funktionsfähiges Frontend weiter.
  5. Ihr Frontend beendet die TCP-Verbindung.

Jetzt geschieht die Zauberei in den Schritten 4 und 5. Sehen wir uns also genauer an, was sie tun.

Ihre Firewall kennt die Liste der Frontends ( FE 1und FE 2) und wählt eines davon basierend auf einem bestimmten Aspekt des Datenflusses aus (z. B. durch Hashing der Quell-IP und des Ports unter anderen Headern). Es muss aber auch sichergestellt werden, dass der Datenverkehr an ein funktionsfähiges Frontend weitergeleitet wird, da Sie sonst den Datenverkehr auf ein Schwarzes Loch bringen. Wenn Sie zum Beispiel OpenBSD benutzen, können Sie es benutzen relayd. Wasrelayddies ist ganz einfach: Es überprüft alle Frontends auf Fehlerfreiheit (z. B. indem es ihnen eine HTTP-Prüfanforderung sendet) und fügt sie, wenn ein Frontend fehlerfrei ist, einer Tabelle hinzu, die die Firewall verwendet, um den nächsten Hop der Pakete eines bestimmten Datenflusses auszuwählen . Wenn ein Frontend die Integritätsprüfungen nicht besteht, wird es aus der Tabelle entfernt und es werden keine Pakete mehr an es gesendet. Bei der Weiterleitung eines Pakets an ein Frontend tauscht die Firewall lediglich die Ziel-MAC-Adresse des Pakets gegen die des ausgewählten Frontends aus.

In Schritt 5 werden die Pakete vom Benutzer von Ihrem Load Balancer empfangen (sei es Lack, Nginx oder was auch immer). Zu diesem Zeitpunkt ist das Paket noch an Ihre öffentliche IP-Adresse gerichtet, sodass Sie Ihre VIPs über die Loopback-Schnittstelle aliasisieren müssen. Dies wird als DSR (Direct Server Return) bezeichnet, da Ihre Frontends die TCP-Verbindung beenden und die Firewall dazwischen nur Simplex-Verkehr sieht (nur eingehende Pakete). Ihr Router leitet ausgehende Pakete direkt an die Router des Internetdienstanbieters zurück. Dies ist besonders gut für HTTP-Datenverkehr geeignet, da Anforderungen in der Regel kleiner sind als Antworten, manchmal sogar erheblich. Nur um klar zu sein: Dies ist keine OpenBSD-spezifische Sache und wird häufig auf Websites mit hohem Datenverkehr verwendet.

Fallstricke:

  • Endbenutzer stellen eine direkte Verbindung zu Ihren Front-End-Servern her, da Sie DSR verwenden. Vielleicht war es bereits der Fall, aber wenn nicht, müssen Sie sicherstellen, dass sie ausreichend gesichert sind.
  • Wenn Sie OpenBSD verwenden, achten Sie darauf, dass der Kernel Single-Threaded ist, damit die Leistung eines einzelnen CPU-Kerns den Durchsatz einer Firewall einschränkt. Dies kann je nach Art der Netzwerkkarte und der angezeigten Paketrate ein Problem sein. Es gibt Möglichkeiten, dieses Problem zu lösen (mehr dazu weiter unten).

Zweite Strategie: ohne Firewall

Diese Strategie ist effizienter, aber schwieriger einzurichten, da sie stärker von den Besonderheiten der von Ihnen verwendeten Router abhängt. Die Idee ist, die Firewall oben zu umgehen und die Router die ganze Arbeit machen zu lassen, die die Firewalls gemacht haben.

Sie benötigen Router, die portspezifische L3 / L4-ACLs, BGP und ECMP sowie Policy Based Routing (PBR) unterstützen. Nur High-End-Router unterstützen diese Funktionen, und für die Verwendung von BGP fallen häufig zusätzliche Lizenzgebühren an. Dies ist in der Regel immer noch billiger als der Hardwarelastausgleich und zudem wesentlich einfacher zu skalieren. Das Gute an diesen High-End-Routern ist, dass sie in der Regel eine Übertragungsrate aufweisen (z. B. können sie die Verbindung auch auf 10-GbE-Schnittstellen immer maximal nutzen, da alle Entscheidungen, die sie treffen, in Hardware von ASICs getroffen werden).

Wenden Sie auf die Ports, auf denen sich Ihre ISP-Uplinks befinden, die ACL an, die sich früher in der Firewall befand (z. B. "Nur 80 / TCP und 443 / TCP auf diese bestimmte IP-Adresse zulassen"). Lassen Sie dann jedes Ihrer Frontends eine BGP-Sitzung mit Ihrem Router aufrechterhalten. Sie können das ausgezeichnete OpenBGPD (wenn Ihre Frontends auf OpenBSD sind) oder Quagga verwenden . Ihr Router prüft den Datenverkehr zu den Frontends, die fehlerfrei sind (da sie ihre BGP-Sitzungen beibehalten). Der Router leitet den Datenverkehr auch mit PBR entsprechend weiter.

Verfeinerungen

  • Bei der Firewall-Pair-Lösung ist es hilfreich, wenn Sie die TCP-Zustände über die Firewalls hinweg synchronisieren können, damit beim Ausfall einer Firewall alles reibungslos auf die andere übergeht. Sie erreichen dies mit pfsync.
    • Beachten Sie, dass pfsyncsich die Paketrate auf Ihren Firewalls normalerweise verdoppelt.
    • HTTP ist ein zustandsloses Protokoll, daher ist es nicht das Ende der Welt, wenn Sie während eines Firewall-Failovers alle Verbindungen zurücksetzen, weil Sie es nicht verwenden pfsync.
  • Wenn Sie einer einzelnen Firewall entwachsen sind, können Sie ECMP auf Ihrem Router verwenden, um Ihren Datenverkehr an mehr als ein Firewall-Paar weiterzuleiten.
  • Wenn Sie mehr als ein Firewall-Paar verwenden, können Sie auch alle aktivieren / deaktivieren. Sie können dies erreichen, indem die Firewalls eine BGP-Sitzung mit den Routern aufrechterhalten, ähnlich wie die Frontends eine Sitzung im 2. Entwurf ohne Firewalls aufrechterhalten müssen.

relaydBeispielkonfigurations

Siehe auch HOWTO unter https://calomel.org/relayd.html

vip = "1.2.3.4" # Ihre öffentliche IP-Adresse
               # (Sie können mehrere haben, müssen es aber nicht)
fe1 = "10.1.2.101"
fe2 = "10.1.2.102"
fe3 = "10.1.2.103"
fe4 = "10.1.2.104" # Sie können beliebig viele Frontends haben.
int_if = "em0"
Tabelle <fe> {$ fe1 Wiederholung 2, $ fe2 Wiederholung 2, $ fe3 Wiederholung 2, $ fe4 Wiederholung 2}
Tabelle <Fallback> {127.0.0.1}

webtraffic umleiten {
        lausche auf $ vip port 80
        Sitzungs-Timeout 60
        route to <fe> check http "/healthcheck.html" digest "(die sha1sum von healthcheck.html)" interface $ int_if
}
Tsuna
quelle
2

Persönlich habe ich zu diesem Zeitpunkt einfachere, weniger konfigurierbare Hardware-Load-Balancer gewählt - beispielsweise die ACE / ASAs von Cisco, Foundry ServerIrons oder sogar Zeus ZXTMs (eine SW LB, die für sehr hohe Lasten entwickelt wurde).

Chopper3
quelle
Mit anderen Worten skalieren up ? Solch ein LB wird bei einer bestimmten Anzahl von Verbindungen (usw.) immer noch maximal sein. Was dann? Das ist wirklich meine Frage. Vielen Dank!
z8000
1
Wirklich große Sites verwenden nur viele Hochleistungs-LBs, die unter irgendeiner Form von DNS-Round-Robin laufen - es ist für die meisten im Moment gut genug und kann Hunderte von Millionen von Verbindungen verarbeiten. Das heißt, es ist die Frage, warum so viele Verbindungen natürlich offen bleiben müssen ...
Chopper3
Ist das interne RRDNS gemeint? Gut, daran habe ich nicht gedacht. Betreff: Verbindungen öffnen ... Ich suche nach Optionen für eine App, bei der im Laufe der Zeit Aktualisierungen an verbundene Clients gesendet werden müssen, wenn Ereignisse irgendwo im Backend auftreten. Ich bin zwischen einem benutzerdefinierten TCP-Server oder vielen offenen HTTP-Verbindungen hinter einem SLB hin- und hergerissen. Vielen Dank für Ihre Kommentare.
z8000
Ich würde denken, dass es externe RRDNS sein müsste. Zum Beispiel würde Twitter.com RRDNS verwenden, um Anfragen zu lösen und an eine von vielen großen LBs zu verteilen, die dann die Last auf die Server verteilen würden.
Robert
Ja, Robert, Sie haben Recht, zum Beispiel verwenden wir Cisco GSS-Boxen, um Standort-für-Standort-RR durchzuführen.
Chopper3
1

Statt ständig so viele offene Verbindungen zu halten, um Antworten zu senden, sollten Sie Ihre Anwendung so codieren, dass Clients Ihre Server regelmäßig so oft wie nötig abfragen.

Erfordert das, was Sie gerade tun, tatsächlich eine Antwort in genau dieser Millisekunde, oder kann ein Client 15/20 Sekunden bis zur nächsten Abfrageperiode warten?

Mxx
quelle
0

Ein typischer Ansatz wäre, einen Cluster zu erstellen, der groß genug ist, um die erforderliche Last zu bewältigen, und einen SLB zu verwenden, der einen deterministischen Lastausgleich durchführen kann (für den Fall von dauerhaften Verbindungen).

So etwas wie CARP verwendet einen Hash der anfragenden IP, um zu bestimmen, welcher Back-End-Webserver die Anfrage bearbeiten würde. Dies sollte deterministisch sein, ist aber nicht sehr nützlich, wenn sich eine Firewall oder NAT vor Ihrem Load Balancer befindet.
Sie können auch IPVS als nützlich erachten , wenn Sie unter Linux arbeiten.

Martin
quelle
Was Sie über Karpfen behaupten, ist so weit davon entfernt, wie es funktioniert, ich würde nicht wissen, wo ich anfangen soll! + -0 für die Erwähnung von IPVS.
3.
@ 3molo ... huh? Siehe net.inet.carp.arpbalance unter linux.com/archive/feed/35482 "..CARP-Quell-Hashes für die Ursprungs-IP einer Anfrage. Der Hash wird dann verwendet, um einen virtuellen Host aus dem verfügbaren Pool für die Bearbeitung der Anfrage auszuwählen . "
Paul