Sie sind nicht angemeldet.

DaBu

Administrator

  • »DaBu« ist der Autor dieses Themas

Beiträge: 1 107

Danksagungen: 557

  • Nachricht senden

1

Dienstag, 25. September 2018, 19:34

Eine Art Cluster Anwendung

Ich hab da mal wieder eine Frage, vll. gibt es ja jemand der eine schlaue Antwort dazu liefern kann.

Folgendes Szenario:

Ich habe ein System, welches Aufgaben abarbeiten soll. Um das ganze ein bisschen ausfallsicherer zu gestalten soll es auf mehreren Servern laufen. Außerdem ist eine Anforderung, dass einzelne Nodes vielleicht auch in einem ganz anderen Land laufen sollen. Das System soll anhand der einzelnen Server redundant sein. Das heißt jeder Server wäre in der Lage alle Aufgaben eines anderen Servers zu übernehmen.

Das ganze klingt jetzt wahrscheinlich etwas verwirrend und durcheinander, deswegen vll. besser mal ein handfestes Beispiel.

Wir möchten regelmäßig prüfen ob eine Webseite noch online ist. Dazu können wir jetzt einfach auf einem Server eine schleife laufen lassen und immer wieder checken ob die gewünschte Webseite noch online ist.
Zum einen könnte der Server nun ausfallen und zum anderen kann es auch sein, dass der Server aus anderen gründen keine Verbindung zu genau dieser Webseite bekommt. Das hießt, zum einen müsste man die Daten auf min. 2 Servern vorhalten und zum anderen müsste der eine Server den anderen fragen können ob dieser mal eben für ihn prüft ob die Webseite für ihn noch online ist.

Jetzt habe ich mir mehrere Ansätze überlegt.

Ansatz 1.
Wir haben ein zentralen Server, der verwaltet die Datenbank und bietet auch die UI für die eigentliche Anwendung an. Alle Task sind einem der vielen anderen Servern zugeordnet, nennen wir sie mal Satelliten.
Jeder Satellit arbeitet nun brav seine Aufgaben ab und wenn er mal keine Verbindung zu einer Seite aufbauen kann fragt er einen anderen Satelliten. Fällt nun ein Satellit ganz aus, dann muss der zentrale Server die Task an alle anderen aufteilen. Kommt der Satellit wieder ins System, dann bekommt er von allen Systemen ein paar Aufgaben ab.

Der Ansatz ist für mich der einfachste, leider steht und fällt alles mit dem zentralen Server. ist dieser Offline kippt das ganze System.

Ansatz 2.
Wir haben keinen zentralen Server, sondern nur unsere Satelliten, diese werden über eine Konfiguration gepflegt. Alle haben alle Daten. Schlägt die überprüfung einer Webseite nun fehl, so fragt der Server wie beim 1. Ansatz einen der anderen Satelliten an. Fällt aber nun ein Satellit aus, so müssen die anderen die Aufgaben übernehmen. Dadurch dass alle, alle Daten haben, wissen sie ja was nun nicht mehr erledigt wird. Allerdings müsste entschieden werden, wer was übernimmt. Man könnte jetzt sagen, immer der oberste laufende Server in der Konfiguration übernimmt die Koordinierung und verteilt die Aufgaben neu.

Der Ansatz ist ziemlich komplex und benötigt sehr viel Planung, dafür würde das System immer funktionieren und man könnte wahllos anfangen Server einfach rauszuwerfen und hätte damit eine extrem hohe Wartbarkeit.
Ein zentrales Userinterface müsste dann auf einem externen einen Server liegen und alle Satelliten füttern. Diese UI könnte dann ausfallen, aber das System selbst würde weiter laufen.


Ich hoffe es ist in etwa klar was mein Gedankengang ist. Gibt es bessere Ansätze oder hat jemand Beispiele (wenn möglich auf php basis)? Ich möchte so gut es geht lieber viele kleine Server nutzen statt ein dickes Cluster aufbauen. Man könnte sicher bei Ansatz 1. einfach 2 Webserver nehmen mit einer Master/Slave Kombi im Hintergrund, damit der Zentrale Dienst niemals ausfällt, aber dass übersteigt meinen Geldbeutel ;)
Irgendwas mit Medien

2

Mittwoch, 26. September 2018, 09:18

Wenn deine Daten ebenfalls verteilt sein sollen, dann brauchst du zum Beispiel eine DB-Replikation. Das gibts wohl bei PostgreSQL in einer sehr ausgefeilten Variation.
Dazu kannste dann auf jedem Knoten eine komplette Umgebung aufbauen. Die Domains die du dann Hosten willst können dann von einem Frontend Server per Redirect auf den jeweiligen Node geleitet werden.

Das Kriterium für die Umleitung kann zum Beispiel auch das Land sein aus dem der Aufruf erfolgt.

Wenn das Frontend ausfällt, müsstest du eh per DNS-Eintrag ändern auf deinen Ersatz umschalten, solange du keine spezielle Hardware einsetzen willst.

gmx hat das früher so gemacht. Man ist quasi nach dem anmelden auf einen Server gmx123.com umgeleitet worden. Auf dem lief dann das eigentliche Frontend.
Das Frontend kann, weil es ja nur die Redirects macht, auch aus mehreren Raspberry PI bestehen die hinter einem Load-Balancer liegen. Das würde dann wahrscheinlich auch für das Frontend eine entsprechende Ausfallsicherheit bieten.

DaBu

Administrator

  • »DaBu« ist der Autor dieses Themas

Beiträge: 1 107

Danksagungen: 557

  • Nachricht senden

3

Mittwoch, 26. September 2018, 21:31

Das hört sich schon mal gut an. Wenn ich nichts besseres finde werde ich mich wohl dann doch auf Variante 1 stützen. Hab mir schon 2 Broadcastalgorithmen angesehen für die Verteilung, falls ich das selbst machen will. Ich sehe auch in der Verteilung nicht das riesen Problem.

Notfalls stellt jeder Satellit ein json File zur Verfügung dann ist die Verteilung super einfach. Ich habe ja auch nicht viele Daten. Viel mehr habe ich vor dem Ausfall eines Systems Angst. Es muss ja dann jemand übernehmen und was passiert wenn das System auf einmal wieder online geht und selbst anfängt zu prüfen. Fragen über Fragen
Irgendwas mit Medien

Nik101010

Anfänger

Beiträge: 41

Wohnort: Stuttgart

Danksagungen: 8

  • Nachricht senden

4

Sonntag, 30. September 2018, 14:28

Also konzeptionell bekomme ich immer Bauchschmerzen sobald ich eine zentrale Instanz habe. Ja, ein zentraler Koordinator vereinfacht vieles, aber hat eben auch einen ganz simplen Nachteil: Single Point of Failure. Der schnelle Tod für jegliche HA v.a. weil du hier auch ein massives Skalierungsproblem bekommst.

Auch verteilte Transaktionen sind teuer und kosten mit jeder weiteren Skalierung immer mehr, weil sich immer mehr Instanzen koordinieren müssen. Daher würde ich auch den Ansatz nur dann verfolgen, wenn es sich nicht anders lösen lässt.

Was ist jetzt also das "Anders"?

Die einfachste, wenn auch oftmals anspruchvollste Lösung ist es, die Operationen in einem verteilen System idempotent zu gestalten. Heißt wird dieselbe Operation mit denselben Parametern ausgeführt, hat sie immer das gleiche Ergebnis (egal, wie oft die Operation ausgeführt wird). In diesem Fall kannst du die Koordination zwischen den Instanzen komplett optimistisch gestalten, sprich anstatt von Locking setzt du auf Events, dass bestimmte Aktionen durchgeführt werden / wurden (je nach Priorität der Aktion). Das Verteilen der Events wäre z.B. über einen Eventbus ziemlich einfach lösbar.
Kommt jetzt ein Event, dass eine Operation durchgeführt wurde, bei einem Knoten im System zu spät an, so wird eine bestimmte Operation ein zweites Mal ausgeführt, aber dank Idempotenz ändert das nichts am Zustand des Gesamtsystems.

Übertragen auf dein Beispiel mit den Online Checks könnte eine mögliche Lösung folgendermaßen aussehen. Ich nehme der Einfachkeit halber an, dass die zu überprüfenden URL de facto statisch sind, ansonsten sag nochmal bescheid, ich hab auch schon Ideen im Kopf, bin aber aktuell tippfaul ;)
Online Checks sind out of the box idempotent, da du keinen Zustand veränderst. Jeder Knoten im System holt sich beim Starten eine Konfiguration mit allen zu überprüfenden URLs (z.B. über eine Konfigurationsdatei, die du auf allen Server verteilst). Diese URLs überträgt sich der Knoten in eine lokale in Memory Datenbank. Jetzt wartet er das Intervall (Is) ab, in dem alle URL überprüft sein sollten. Während der Zeit empfängt der Knoten allerdings schon alle Events auf dem Eventbus und aktualisiert seine lokale Datenbank. Empfängt er ein Event, dass ein bestimmter Knoten online ist, so trägt er sich die Überprüfungszeit als letzte Onlinezeit in seine lokale Datenbank ein. Nach Is beginnt der Knoten auch die URL auf ihren Onlinestatus zu überprüfen. Hierzu wählt er in einem beliebigen Intervall Ip (Ip < Is) die URL aus, die als nächstes überprüft werden müsste. Bevor er die URL überprüft sendet er ein Event an alle anderen Knoten, dass er die URL (u) zum Zeitpunkt (t1) überprüft. Alle anderen Knoten aktualisieren ihre lokale Datenbank, dass u zu t1 online war. Diese überprüfen u somit erst wieder, wenn u die am längsten nicht mehr überprüfte URL war. Erreicht der Knoten u zum Zeitpunkt t1, so sendet er kein weiteres Event. Erreicht der Knoten u die URL nicht, so informiert er ebenfalls via Event alle anderen Knoten, dass u offline ist. Alle Knoten aktualisieren jetzt ihre lokale Datenbank, dass u offline ist.
Fällt der Knoten aus nachdem er das Event gesendet hat, aber bevor er die URL überprüfen konnte, so ist kurzzeitig eine falsche Information im System, aber mit den passenden Intervallen lässt sich diese falsche Information verhältnismäßig schnell aktualisieren, oder du arbeitest mit einem Tri-State: "In Überprüfung ab Zeit", "Online @ Zeit" und "Offline" und einem Erfolgsevent und der "In Überprüfung" Status bekommt einen Timeout.

Die UI kann ihre Informationen von jedem Knoten abfragen, der länger als Is im System angemeldet war. Hierzu könnten z.B. alle Knoten hinter einem API Gateway aufgehängt sein, über das die UI die Informationen abruft.

Weitere Optimierungen wäre z.B. Aufteilen, der überprüfenden Knoten und der Informationshaltenden Knoten auf 2 verschiedene Service Arten. Diese Services würden sich dann gegenseitig via Service Discovery finden.


Kritische Services wären die Service Discovery und das API Gateway. Diese müsste man mit einem klassischen Loadbalancer Ansatz für HA rüsten.
PS: Dieser Post ist runtergeschrieben und nicht Korrektur gelesen … sollte er teilweise unverständlich sein gerne nachfragen (shame on me ...)

Ähnliche Themen

Social Bookmarks