Clusterverwaltung in Orleans
Orleans bietet Clusterverwaltung über ein integriertes Mitgliedschaftsprotokoll, das manchmal als Clustermitgliedschaft bezeichnet wird. Das Ziel dieses Protokolls besteht darin, dass sich alle Silos (Orleans-Server) auf die Gruppe der derzeit aktiven Silos einigen, fehlerhafte Silos erkennen und neuen Silos den Beitritt zum Cluster gestatten.
Das Protokoll basiert auf einem externen Dienst, um eine Abstraktion von IMembershipTable bereitzustellen. IMembershipTable ist ein flacher dauerhafter Tisch, den wir für zwei Zwecke verwenden. Erstens wird sie als Treffpunkt für Silos verwendet, um sich gegenseitig zu finden und damit Orleans-Clients Silos finden können. Zweitens wird sie verwendet, um die aktuelle Mitgliedschaftsansicht (Liste der aktiven Silos) zu speichern, und sie hilft dabei, die Einigung über die Mitgliedschaftsansicht zu koordinieren.
Wir verfügen derzeit über 6 Implementierungen der IMembershipTable: basierend auf Azure Table Storage, Azure Cosmos DB, ADO.NET (PostgreSQL, MySQL/MariaDB, SQL Server, Oracle), Apache ZooKeeper, Consul IO, AWS DynamoDB, MongoDB, Redis, Apache Cassandraund eine In-Memory-Implementierung für die Entwicklung.
Zusätzlich zur IMembershipTable nimmt jedes Silo an einem vollständig verteilten Peer-to-Peer-Mitgliedschaftsprotokoll teil, das fehlerhafte Silos erkennt und eine Einigung über eine Gruppe aktiver Silos erzielt. Wir beschreiben gerade die interne Implementierung des Mitgliedschaftsprotokolls von Orleans, wie unten dargestellt.
Das Mitgliedschaftsprotokoll
Beim Start fügt jedes Silo einen Eintrag für sich selbst in eine bekannte, gemeinsam genutzte Tabelle ein, wobei eine Implementierung von IMembershipTable verwendet wird. Eine Kombination aus Siloidentität (
ip:port:epoch
) und Dienstbereitstellungs-ID (Cluster-ID) wird als eindeutige Schlüssel in der Tabelle verwendet. Die Epoche ist lediglich die Zeit in Takten (Ticks), als dieses Silo gestartet wurde, und somit ist garantiert, dassip:port:epoch
in einer bestimmten Orleans-Bereitstellung eindeutig ist.Silos überwachen sich gegenseitig direkt über Anwendungstests („are you alive“–
heartbeats
). Tests werden als direkte Nachrichten von Silo zu Silo über dieselben TCP-Sockets gesendet, über die Silos kommunizieren. Auf diese Weise korrelieren die Messungen vollständig mit tatsächlichen Netzwerkproblemen und dem Serverzustand. Jedes Silo testet eine konfigurierbare Gruppe anderer Silos. Ein Silo wählt aus, wer getestet werden soll, indem es konsistente Hashes für die Identität anderer Silos berechnet und so einen virtuellen Ring aller Identitäten bildet und X Nachfolgersilos auf dem Ring auswählt (dies ist eine bekannte verteilte Methode namens konsistentes Hashing und wird häufig in vielen verteilten Hashtabellen wie Chord DHT verwendet).Wenn ein Silo S keine Y Testantworten von einem überwachten Server P erhält, verdächtigt es diesen, indem es seinen Verdacht mit Zeitstempel in die Zeile von P in der IMembershipTable schreibt.
Wenn P innerhalb von K Sekunden mehr als Z Verdachtsmomente hat, schreibt S „P ist inaktiv” in die Zeile von P und sendet eine Momentaufnahme der aktuellen Mitgliedschaftstabelle an alle anderen Silos. Silos aktualisieren die Tabelle regelmäßig. Daher dient die Momentaufnahme als Optimierung, um die Zeit zu reduzieren, die alle Silos benötigen, um die neue Mitgliedsansicht kennenzulernen.
Ausführlichere Informationen:
Ein Verdacht wird in die IMembershipTable in eine spezielle Spalte in der Zeile geschrieben, die P entspricht. Wenn S P verdächtigt, schreibt er: „at time TTT S suspected P“ (zur Zeit TTT hat S P verdächtigt).
Ein Verdacht reicht nicht aus, um P für inaktiv zu erklären. Sie benötigen Z Verdachtseinträge aus verschiedenen Silos in einem konfigurierbaren Zeitfenster T, in der Regel 3 Minuten, um P für inaktiv zu erklären. Der Verdacht wird unter Verwendung der optimistischen Nebenläufigkeitssteuerung geschrieben, die von der IMembershipTable bereitgestellt wird.
Das verdächtigende Silo S liest die Zeile von P.
Wenn
S
der letzte Verdächtigende ist (es gab bereits Z minus 1 Verdächtigende innerhalb eines Zeitraums T, wie in der Spalte „Verdacht“ geschrieben), beschließt S, P für inaktiv zu erklären. In diesem Fall fügt sich S selbst der Liste der Verdächtigenden hinzu und schreibt außerdem in die „Status“-Spalte von P, dass P inaktiv (Dead) ist.Andernfalls fügt sich S, wenn S nicht der letzte Verdächtigende ist, lediglich der Spalte der Verdächtigenden hinzu.
In beiden Fällen verwendet das Rückschreiben die Versionsnummer oder das ETag, die/das gelesen wurde, sodass die Aktualisierungen dieser Zeile serialisiert werden. Falls der Schreibvorgang aufgrund eines Versions-/ETag-Konflikts fehlgeschlagen ist, führt S einen Wiederholungsversuch durch (erneutes Lesen und der Versuch, zu schreiben, es sei denn, P war bereits als inaktiv markiert).
Allgemein betrachtet ist diese Abfolge von „lesen, lokal ändern, zurückschreiben“ eine Transaktion. Dazu verwenden wir jedoch nicht unbedingt Speichertransaktionen. Der „Transaktion“scode wird lokal auf einem Server ausgeführt, und wir verwenden optimistische Nebenläufigkeit, die von der IMembershipTable bereitgestellt wird, um Isolation und Unteilbarkeit (Atomarität) sicherzustellen.
Jedes Silo liest regelmäßig die gesamte Mitgliedschaftstabelle für seine Bereitstellung. Auf diese Weise erfahren Silos über neue beitretende Silos sowie über andere Silos, die für inaktiv erklärt werden.
Momentaufnahmeübertragung: Um die Häufigkeit der periodischen Tabellenabfragen zu reduzieren, sendet ein Silo jedes Mal, wenn es einen Eintrag in die Tabelle vornimmt (Verdacht, neuer Beitritt usw.), eine Momentaufnahme des aktuellen Tabellenzustands an alle anderen Silos. Da die Mitgliedschaftstabelle konsistent und monoton versioniert ist, erzeugt jedes Update eine eindeutig versionsierte Momentaufnahme, die sicher geteilt werden kann. Dies ermöglicht die umgehende Verbreitung von Mitgliedschaftsänderungen, ohne auf den regulären Lesezyklus zu warten. Der regelmäßige Lesevorgang wird weiterhin als Fallbackmechanismus beibehalten, falls die Momentaufnahmeverteilung fehlschlägt.
Geordnete Mitgliedschaftsansichten: Das Mitgliedschaftsprotokoll stellt sicher, dass alle Mitgliedschaftskonfigurationen global vollständig sortiert sind. Diese Sortierung bietet zwei wichtige Vorteile:
Garantierte Konnektivität: Wenn ein neues Silo dem Cluster beitritt, muss es die bidirektionale Konnektivität zu jedem anderen aktiven Silo validieren. Wenn ein bestehendes Silo nicht reagiert (was möglicherweise ein Netzwerkverbindungsproblem anzeigt), darf das neue Silo nicht beitreten. Dadurch wird die vollständige Verbindung zwischen allen Silos im Cluster beim Start sichergestellt. Beachten Sie den Hinweis zu IAmAlive im Folgenden zur Ausnahme im Falle der Notfallwiederherstellung.
Konsistente Verzeichnisaktualisierungen: Protokolle höherer Ebene, wie z. B. das verteilte Getreideverzeichnis, verlassen sich auf alle Silos mit einer konsistenten, monotonen Ansicht der Mitgliedschaft. Dies ermöglicht eine intelligentere Auflösung doppelter Grain-Aktivierungen. Weitere Informationen finden Sie in der Grain-Verzeichnis--Dokumentation.
Implementierungsdetails:
Die IMembershipTable erfordert atomare Aktualisierungen, um eine globale Gesamtreihenfolge von Änderungen zu gewährleisten.
- Implementierungen müssen sowohl die Tabelleneinträge (Liste der Silos) als auch die Versionsnummer atomisch aktualisieren.
- Dies kann mithilfe von Datenbanktransaktionen (wie in SQL Server) oder atomischer Vergleichs- und Swap-Vorgängen mithilfe von ETags (wie in Azure Table Storage) erreicht werden.
- Der spezifische Mechanismus hängt von den Funktionen des zugrunde liegenden Speichersystems ab.
Eine spezielle Mitgliedschaftsversion-Zeile in der Tabelle verzeichnet Änderungen.
- Jeder Eintrag in die Tabelle (Verdacht, Inaktiv-Erklärungen, Verknüpfungen) erhöht diese Versionsnummer.
- Alle Schreibvorgänge werden mithilfe von Atomaktualisierungen in dieser Zeile serialisiert.
- Die monoton steigende Version sorgt für eine totale Reihenfolge aller Änderungen der Mitgliedschaft.
Wenn Silo S den Status von Silo P aktualisiert:
- S liest zuerst den aktuellen Tabellenstatus.
- In einem einzigen atomaren Vorgang werden beide Zeilen von P aktualisiert und die Versionsnummer erhöht.
- Wenn das Atomupdate fehlschlägt (z. B. aufgrund gleichzeitiger Änderungen), wird der Vorgang mit exponentiellem Backoff wiederholt.
Überlegungen zur Skalierbarkeit:
Durch die Serialisierung aller Schreibvorgänge über die Versionszeile kann die Skalierbarkeit aufgrund erhöhter Konkurrenz beeinträchtigt werden. Das Protokoll hat sich im Einsatz mit bis zu 200 Silos bewährt, kann aber Herausforderungen begegnen, wenn es über tausend Silos hinausgeht. Bei sehr großen Bereitstellungen bleiben andere Teile von Orleans (Messaging, Grain Directory, Hosting) auch dann skalierbar, wenn Mitgliedschaftsupdates zu einem Engpass werden.
Standardkonfiguration: Die Standardkonfiguration wurde unter Produktionsbedingungen in Azure manuell optimiert. Standardmäßig wird jeder Silo von drei anderen Silos überwacht, zwei Verdachtsfälle reichen aus, um einen Silo tot zu deklarieren, Verdächtigungen nur aus den letzten drei Minuten (andernfalls sind sie veraltet). Tests werden alle zehn Sekunden gesendet, und Sie müssten drei Tests verpassen, um ein Silo zu verdächtigen.
Selbstüberwachung: Der Fehlerdetektor umfasst Ideen aus der HashiCorp-Lifeguard-Forschung (Dokument, Vortrag, Blog) zur Verbesserung der Clusterstabilität während katastrophaler Ereignisse, bei denen ein großer Teil des Clusters teilweise ausfällt. Die
LocalSiloHealthMonitor
-Komponente bewertet die Integrität jedes Silos anhand mehrerer Heuristiken:- Aktiver Status in der Mitgliedschaftstabelle
- Keine Verdachtsfälle aus anderen Silos
- Letzte erfolgreiche Testantworten
- Zuletzt empfangene Testanforderungen
- Reaktionsfähigkeit des Thread-Pools (Arbeitsaufgaben, die innerhalb einer Sekunde ausgeführt werden)
- Timer-Genauigkeit (Auslösung innerhalb von 3 Sekunden nach Zeitplan)
Die Integritätsbewertung eines Silos wirkt sich auf seine Test-Timeouts aus: ungesunde Silos (Punktzahl 1-8) haben im Vergleich zu gesunden Silos (Punktzahl 0) längere Timeouts. Dies hat zwei Vorteile:
- Gibt mehr Zeit, um Tests erfolgreich durchzuführen, wenn das Netzwerk oder System unter Stress steht.
- Macht es wahrscheinlicher, dass fehlerhafte Silos abgewählt werden, bevor sie fälschlicherweise fehlerfreie Silos auswählen können
Dies ist besonders wertvoll in Szenarien wie dem Mangel an Thread-Pools, wo langsame Knoten sonst fälschlicherweise gesunde Knoten unter Verdacht stellen könnten, nur weil sie Antworten nicht schnell genug verarbeiten können.
Indirektes Testen: Ein weiteres Lifeguard-inspiriertes Feature, das die Genauigkeit der Fehlererkennung verbessert, indem es die Wahrscheinlichkeit verringert, dass ein ungesundes oder partitioniertes Silo fälschlicherweise ein gesundes Silo als inaktiv deklariert. Wenn ein Überwachungssilo noch zwei Testversuche für ein Zielsilo hat, bevor darüber abgestimmt wird, ob es für inaktiv erklärt werden soll, wird indirektes Testen verwendet:
- Das Überwachungssilo wählt zufällig ein anderes Silo als Vermittler aus und bittet es, das Ziel zu testen.
- Der Vermittler versucht, das Zielsilo zu kontaktieren.
- Wenn das Ziel nicht innerhalb des Timeout-Zeitraums reagiert, sendet der Vermittler eine negative Bestätigung.
- Wenn das Überwachungssilo eine negative Rückmeldung des Vermittlers erhalten hat und der Vermittler sich selbst fehlerfrei erklärt (durch Selbstüberwachung, wie oben beschrieben), gibt das Überwachungssilo eine Abstimmung ab, um das Ziel für inaktiv zu erklären.
- Mit der Standardkonfiguration von zwei erforderlichen Stimmen zählt eine negative Bestätigung eines indirekten Tests als beide Stimmen, was eine schnellere Deklaration von inaktiven Silos ermöglicht, wenn der Fehler durch mehrere Perspektiven bestätigt wird.
Erzwingen der vollständigen Fehlererkennung: Sobald ein Silo in der Tabelle als inaktiv erklärt wurde, wird es von allen als inaktiv betrachtet, selbst wenn es nicht tatsächlich inaktiv ist (nur vorübergehend partitioniert ist oder Taktnachrichten verloren gegangen sind). Alle hören auf, mit dem Silo zu kommunizieren, und sobald es erfährt, dass es inaktiv ist (indem es seinen neuen Status aus der Tabelle liest), inaktiviert es sich selbst („Suizid“) und beendet seinen Prozess. Aus diesem Grund muss eine Infrastruktur vorhanden sein, um das Silo als neuen Prozess neu zu starten (beim Start wird eine neue Epochennummer generiert). Wenn es in Azure gehostet wird, geschieht dies automatisch. Wenn diese Infrastruktur nicht vorhanden ist, ist eine andere erforderlich, wie z. B. ein Windows-Dienst, der so konfiguriert ist, dass er bei einem Fehler automatisch neu startet, oder eine Kubernetes-Bereitstellung.
Was geschieht, wenn die Tabelle für einige Zeit nicht zugänglich ist:
Wenn der Speicherdienst ausgefallen oder nicht verfügbar ist oder Kommunikationsprobleme mit ihm auftreten, deklariert das Orleans-Protokoll die Silos NICHT versehentlich als inaktiv. Betriebsbereite Silos funktionieren problemlos weiter. Orleans kann ein Silo jedoch nicht als inaktiv deklarieren (wenn durch verpasste Tests festgestellt wird, dass ein Silo inaktiv ist, kann diese Tatsache nicht in die Tabelle geschrieben werden) und auch den Beitritt neuer Silos nicht zulassen. Die Vollständigkeit wird also darunter leiden, aber die Genauigkeit nicht. Die Partitionierung aus der Tabelle wird nie dazu führen, dass Orleans ein Silo fälschlicherweise als inaktiv deklariert. Im Falle einer partiellen Netzwerkpartition (wenn einige Silos auf die Tabelle zugreifen können und andere nicht), könnte es auch vorkommen, dass Orleans ein inaktives Silo als inaktiv deklariert, wobei es aber einige Zeit dauert, bis alle anderen Silos davon erfahren. Doch auch wenn die Erkennung also verzögert sein könnte, wird Orleans niemals ein Silo aufgrund der Nichtverfügbarkeit der Tabelle fälschlicherweise inaktivieren.
IAmAlive schreibt für Diagnose- und Notfallwiederherstellung:
Zusätzlich zu Takten, die zwischen den Silos gesendet werden, aktualisiert jedes Silo regelmäßig einen „I Am Alive“-Zeitstempel in seiner Zeile in der Tabelle. Dies dient zwei Zwecken:
- Für die Diagnose bietet es Systemadministratoren eine einfache Möglichkeit, die Verfügbarkeit der Cluster zu überprüfen und festzustellen, wann ein Silo zuletzt aktiv war. Der Zeitstempel wird in der Regel alle 5 Minuten aktualisiert.
- Wenn ein Silo den Zeitstempel für die Notfallwiederherstellung für mehrere Zeiträume (über
NumMissedTableIAmAliveLimit
konfiguriert) nicht aktualisiert hat, ignorieren neue Silos sie während der Start-Konnektivitätsprüfung, sodass der Cluster aus Szenarien wiederhergestellt werden kann, in denen Silos ohne ordnungsgemäße Bereinigung abgestürzt sind.
Mitgliedschaftstabelle
Wie bereits erwähnt, wird die Tabelle IMembershipTable als Treffpunkt für Silos verwendet, um sich gegenseitig zu finden und damit Orleans-Clients Silos finden können. Sie hilft außerdem dabei, die Einigung auf die Mitgliedschaftsansicht zu koordinieren. Das Haupt-Orleans Repository enthält Implementierungen für viele Systeme, z. B. Azure Table Storage, Azure Cosmos DB, PostgreSQL, MySQL/MariaDB, SQL Server, Apache ZooKeeper, Consul IO, Apache Cassandra, MongoDB, Redis, AWS DynamoDB und eine In-Memory-Implementierung für die Entwicklung.
Azure Table Storage: In dieser Implementierung verwenden wir die Azure-Bereitstellungs-ID als Partitionsschlüssel und die Siloidentität (
ip:port:epoch
) als Zeilenschlüssel. Zusammen garantieren sie einen eindeutigen Schlüssel pro Silo. Für die Nebenläufigkeitssteuerung verwenden wir die optimistische Nebenläufigkeitssteuerung, basierend auf Azure Table-ETags. Jedes Mal, wenn wir aus der Tabelle lesen, speichern wir das ETag für jede gelesene Zeile und verwenden dieses ETag, wenn wir versuchen, zurückzuschreiben. ETags werden automatisch bei jedem Schreibvorgang vom Azure Table-Dienst zugewiesen und überprüft. Für Transaktionen mit mehreren Zeilen verwenden wir die Unterstützung für Batchtransaktionen, die von Azure Table bereitgestellt wird, wodurch serialisierbare Transaktionen über Zeilen hinweg mit demselben Partitionsschlüssel garantiert werden.SQL Server: In dieser Implementierung wird die konfigurierte Bereitstellungs-ID verwendet, um zwischen Bereitstellungen zu unterscheiden sowie um zu differenzieren, welche Silos zu welchen Bereitstellungen gehören. Die Siloidentität wird als Kombination von
deploymentID, ip, port, epoch
in entsprechenden Tabellen und Spalten definiert. Das relationale Back-End verwendet optimistische Nebenläufigkeitssteuerung und Transaktionen, ähnlich wie bei der Vorgehensweise zur Verwendung von ETags in der Azure Table-Implementierung. Die relationale Implementierung erwartet, dass die Datenbank-Engine das verwendete ETag generiert. Im Fall von SQL Server ist das generierte ETag bei SQL Server 2000 eins, das durch einen Aufruf vonNEWID()
abgerufen wird. Bei SQL Server 2005 und höher wird ROWVERSION verwendet. Orleans liest und schreibt relationale ETags als opakeVARBINARY(16)
-Tags und speichert sie als base64-codierte Zeichenfolgen im Arbeitsspeicher. Orleans unterstützt Mehrzeileneinfügungen mithilfe vonUNION ALL
(für Oracle einschließlich DUAL), das derzeit zum Einfügen von Statistikdaten verwendet wird. Die genaue Implementierung und das Konzept für SQL Server finden Sie unter CreateOrleansTables_SqlServer.sql.Apache ZooKeeper: In dieser Implementierung verwenden wir die konfigurierte Bereitstellungs-ID als Stammknoten und die Siloidentität (
ip:port@epoch
) als dessen untergeordneten Knoten. Zusammen garantieren sie einen eindeutigen Pfad pro Silo. Für die Nebenläufigkeitssteuerung verwenden wir die optimistische Nebenläufigkeitssteuerung, basierend auf der Knotenversion. Jedes Mal, wenn wir aus dem Stammknoten der Bereitstellung lesen, speichern wir die Version für jeden gelesenen untergeordneten Siloknoten und verwenden diese Version, wenn wir versuchen, zurückzuschreiben. Jedes Mal, wenn sich die Daten eines Knotens ändern, wird die Versionsnummer vom ZooKeeper-Dienst atomisch erhöht. Für Transaktionen mit mehreren Zeilen verwenden wir die multi-Methode, die serialisierbare Transaktionen über Siloknoten hinweg mit demselben übergeordneten Bereitstellungs-ID-Knoten garantiert.Consul IO: Wir haben den Schlüssel-Wert-Speicher von Consul verwendet, um die Mitgliedschaftstabelle zu implementieren. Weitere Informationen finden Sie unter Consul-Bereitstellung.
AWS DynamoDB: In dieser Implementierung verwenden wir die Clusterbereitstellungs-ID als Partitionsschlüssel und die Siloidentität (
ip-port-generation
) als RangeKey (Bereichsschlüssel), der die Datensatzeinheit herstellt. Die optimistische Nebenläufigkeit wird durch dasETag
-Attribut hergestellt, indem bedingte Schreibvorgänge in DynamoDB vorgenommen werden. Die Implementierungslogik ist der von Azure Table Storage sehr ähnlich.Apache Cassandra - In dieser Implementierung verwenden wir die Kombination von Dienst-ID und Cluster-ID als Partitionsschlüssel und die Silo-Identität (
ip:port:epoch
) als Zeilenschlüssel. Zusammen garantieren sie eine eindeutige Zeile pro Silo. Für die Parallelitätssteuerung verwenden wir eine optimistische Parallelitätskontrolle basierend auf einer statischen Spaltenversion unter Verwendung einer Lightweight-Transaktion. Diese Versionsspalte wird für alle Zeilen in der Partition oder des Clusters gemeinsam genutzt, sodass die einheitliche inkrementierende Versionsnummer für die Mitgliedschaftstabelle jeden Clusters bereitgestellt wird. In dieser Implementierung gibt es keine Transaktionen mit mehreren Zeilen.In-Memory-Emulation für das Entwicklungssetup. Für diese Implementierung verwenden wir ein spezielles System-Grain. Dieses Grain existiert in einem bestimmten primären Silo, das nur für ein Entwicklungssetup verwendet wird. In jeder realen Produktionsnutzung ist eine Verwendung des primären Silos nicht erforderlich.
Entwurfskonzept
Eine natürliche Frage, die sich stellen könnte, ist, warum man sich bei der Implementierung der Clustermitgliedschaft nicht vollständig auf Apache ZooKeeper oder etcd verlässt, möglicherweise indem ZooKeeper's sofort einsatzbereite Unterstützung für die Gruppenmitgliedschaft mit kurzlebigen Knoten verwendet wird? Warum haben wir uns die Mühe gemacht, unser Mitgliedschaftsprotokoll zu implementieren? Dafür gab es in erster Linie drei Gründe:
Bereitstellung/Hosting in der Cloud:
Zookeeper ist kein gehosteter Dienst. Dies bedeutet, dass Orleans-Kunden in der Cloudumgebung ihre Instanz eines ZK-Clusters bereitstellen/ausführen/verwalten müssten. Das ist nur eine weitere unnötige Belastung, die wir unseren Kunden nicht auferlegen wollten. Durch die Verwendung von Azure Table verlassen wir uns auf einen gehosteten, verwalteten Dienst, der das Leben unserer Kunden erheblich vereinfacht. Verwenden Sie in der Cloud die Cloud grundsätzlich als Plattform (aaP), nicht als Infrastruktur (aaI). Auf der anderen Seite, wenn Sie lokal ausführen und Ihre Server lokal verwalten, stellt die Verwendung von ZK als Implementierung der IMembershipTable eine praktikable Option dar.
Direkte Fehlererkennung:
Bei Verwendung der Gruppenmitgliedschaft von ZK mit kurzlebigen Knoten wird die Fehlererkennung zwischen den Orleans-Servern (ZK-Clients) und den ZK-Servern durchgeführt. Dies muss nicht unbedingt mit den tatsächlichen Netzwerkproblemen zwischen Orleans-Servern korrelieren. Unser Wunsch war es, dass die Fehlererkennung den clusterinternen Zustand der Kommunikation exakt widerspiegelt. Insbesondere gilt in unserem Entwurf ein Orleans-Silo, wenn es nicht mit IMembershipTable kommunizieren kann, nicht als inaktiv und kann weiter arbeiten. Im Gegensatz dazu kann bei Verwendung der ZK-Gruppenmitgliedschaft mit kurzlebigen Knoten eine Trennung von einem ZK-Server dazu führen, dass ein Orleans-Silo (ZK-Client) für inaktiv erklärt wird, während es noch aktiv und voll funktionsfähig ist.
Portabilität und Flexibilität:
Als Teil der Philosophie von Orleans wollen wir keine starke Abhängigkeit von einer bestimmten Technologie erzwingen, sondern setzen eher auf ein flexibles Design, bei dem verschiedene Komponenten mit unterschiedlichen Implementierungen leicht gewechselt werden können. Genau dies ist der Zweck, dem die IMembershipTable-Abstraktion dient.
Eigenschaften des Mitgliedschaftsprotokolls
Kann eine beliebige Anzahl von Fehlern behandeln:
Unser Algorithmus kann eine beliebige Anzahl von Fehlern (d. h. f<=n) behandeln, einschließlich vollständiger Clusterneustarts. Dies steht im Gegensatz zu „traditionellen“ Paxos-basierten Lösungen, die ein Quorum erfordern, das in der Regel eine Mehrheit darstellt. Wir konnten in Produktionssituationen feststellen, dass mehr als die Hälfte der Silos ausgefallen waren. Unser System blieb dabei funktionsfähig, während die Paxos-basierte Mitgliedschaft nicht in der Lage wäre, Fortschritte zu machen.
Datenverkehr an die Tabelle ist sehr niedrig:
Die tatsächlichen Tests werden direkt zwischen Servern ausgetauscht und nicht mit der Tabelle. Dies würde viel Datenverkehr generieren und wäre außerdem unter dem Aspekt der Fehlererkennung weniger genau – wenn ein Silo die Tabelle nicht erreichen könnte, würde es das Schreiben seines „I am alive“-Heartbeats verpassen und von anderen inaktiviert („killed“) werden.
Optimierbare Genauigkeit im Vergleich zu Vollständigkeit:
Obwohl Sie nicht gleichzeitig eine perfekte und genaue Fehlererkennung erzielen können, möchte man doch in der Regel die Möglichkeit haben, die Genauigkeit (ein aktives Silo, sollte nicht für inaktiv erklärt werden) gegenüber der Vollständigkeit (ein Silo, das tatsächlich inaktiv ist, sollte so schnell wie möglich für inaktiv erklärt werden) abzuwägen. Die konfigurierbaren Abstimmungen zum Erklären der Inaktivität und verpasster Tests erlauben, diese beiden gegeneinander abzuwägen. Weitere Informationen finden Sie unter Yale University: Computer Science Failure Detectors.
Skalieren:
Das Protokoll kann Tausende und wahrscheinlich sogar Zehntausende von Servern verarbeiten. Dies steht im Gegensatz zu herkömmlichen Paxos-basierten Lösungen wie Gruppenkommunikationsprotokollen, von denen bekannt ist, dass sie sich nicht über Dutzende hinaus skalieren lassen.
Diagnosen:
Die Tabelle ist auch sehr praktisch für Diagnosen und Problembehandlungen. Die Systemadministratoren können in der Tabelle sofort die aktuelle Liste der aktiven Silos finden sowie den Verlauf aller inaktivierten („killed“) Silos und aller Verdachtseinträge einsehen. Dies ist besonders nützlich bei der Diagnose von Problemen.
Gründe für die Notwendigkeit von zuverlässigem persistentem Speicher für die Implementierung der IMembershipTable:
Wir verwenden beständigen Speicher für die IMembershipTable für zwei Zwecke. Erstens wird sie als Treffpunkt für Silos verwendet, um sich gegenseitig zu finden und damit Orleans-Clients Silos finden können. Zweitens verwenden wir zuverlässigen Speicher, um die Einigung auf die Mitgliedschaftsansicht zu koordinieren. Während wir die Fehlererkennung direkt in Peer-to-Peer-Weise zwischen den Silos durchführen, speichern wir die Mitgliedschaftsansicht in zuverlässigem Speicher und verwenden den Mechanismus zur Nebenläufigkeitssteuerung, der von diesem Speicher bereitgestellt wird, um eine Einigung darüber zu erzielen, wer aktiv und wer inaktiv ist. Auf diese Weise lagert unser Protokoll gewissermaßen das schwierige Problem des verteilten Konsens in die Cloud aus. So nutzen wir die Leistungsfähigkeit der zugrunde liegenden Cloudplattform voll aus und verwenden sie wirklich als Platform-as-a-Service (PaaS).
Direkte IAmAlive-Schreibvorgänge in die Tabelle nur zu Diagnosezwecken:
Zusätzlich zu Heartbeats, die zwischen den Silos gesendet werden, aktualisiert jedes Silo regelmäßig eine „I Am Alive“-Spalte in seiner Zeile in der Tabelle. Diese „I Am Alive“-Spalte wird nur für die manuelle Problembehandlung und Diagnose verwendet und nicht vom Mitgliedschaftsprotokoll selbst. Dieses wird in der Regel viel seltener geschrieben (einmal alle 5 Minuten) und dient Systemadministratoren als sehr nützliches Tool, um die Aktivität des Clusters zu überprüfen oder einfach herauszufinden, wann das Silo zuletzt aktiv war.
Danksagung
Wir möchten den Beitrag von Alex Kogan zur Gestaltung und Umsetzung der ersten Version dieses Protokolls anerkennen. Diese Arbeit wurde im Rahmen eines Sommerpraktikums bei Microsoft Research im Sommer 2011 durchgeführt.
Die Implementierung von ZooKeeper-basiertem IMembershipTable wurde von Shay Hazor durchgeführt, die Implementierung von SQL IMembershipTable wurde von Veikko Eeva durchgeführt, die Implementierung von AWS DynamoDB IMembershipTable wurde von Gutemberg Ribeiro durchgeführt, und die Implementierung von Consul-basiertem IMembershipTable wurde von Paul North durchgeführt, und schließlich wurde die Implementierung des Apache Cassandra IMembershipTable von OrleansCassandraUtils
von Arshia001 angepasst.