Veröffentlicht am 25-03-2019

Der neugierige Fall von Phantom-Uhren

Die Geschichte unserer Untersuchung unaufgeforderter Consul-Watch-Watches löst aus, und was wir dabei gelernt haben.

gojek.jobs

In einem früheren Beitrag haben wir uns mit dem Konzept von „Uhren“ in Consul befasst und tiefer in ihre Umsetzung eingegangen.

Wie ich bereits in dem Beitrag oben erklärt habe (was ich sehr empfehle, um zu lesen, um einen Zusammenhang zu erhalten), verwendet GO-PAY Consul für die Ermittlung von Services und Consul-Uhren helfen uns, den Status eines Services zu verfolgen.

Dieser Ansatz hat in den letzten zwei Jahren für uns ziemlich gut funktioniert, aber wir hatten einige interessante Probleme bei der Übernahme von Consul in großem Umfang.

In diesem Beitrag werden wir erläutern, wie wir die Probleme identifiziert, untersucht und mehr über den Konsul (und seine Geschichte der Korrekturen) in diesem Prozess erfahren haben. Beachten Sie auch einige Tipps zum Betrieb von Consul in der Produktion mit dem größeren Bienenstockgeist.

Aber ich komme weiter als ich. Beginnen wir am Anfang:

Der Vorfall, der aufhetzt

In einer idealen Welt sollte eine Service-Überwachung nur durch diese drei Situationen ausgelöst werden:

1. Immer wenn sich eine neue Instanz des gerade überwachten Dienstes bei Consul registriert.
2. Eine vorhandene Instanz meldet sich ab, wenn sie ordnungsgemäß heruntergefahren wird.
3. Die Zustandsprüfung dieses Dienstes schlägt fehl.

Zumindest war das unsere Annahme. In der Produktionsumgebung stellten wir jedoch fest, dass die Überwachung für jeden unserer Services in regelmäßigen Abständen ausgelöst wurde, ohne dass sich dies ändert (siehe Abbildung 1).

Abbildung 1: Hier ist RPM die Häufigkeit, mit der

Abbildung 1 zeigt unser APM-Dashboard mit einem hohen Durchsatz von Watch-Retriggern. Dies ist, obwohl der überwachte Dienst während der Ausführung von Consul v0.7.0 fehlerfrei ist

Dann kamen die Konsequenzen

Unser RPC-Framework ist so konzipiert, dass der Datenverkehr gleichmäßig an die fehlerfreien Instanzen eines Zieldienstes weitergeleitet und verteilt wird. Dies geschieht mit einem clientseitigen Load-Balancing-Algorithmus (der in einem späteren Beitrag erweitert wird). Dieser Mechanismus zum dynamischen Umschalten von Verkehr von fehlerhaften Instanzen auf fehlerfreie Instanzen wird mithilfe von Consul Watch Handlers erstellt.

Wir tun dies, indem wir eine Watch-Handler-Funktion mit der entsprechenden Service-Uhr verbinden. Bei jedem Überwachungsauslöser fragt diese Funktion den Consul-Katalog ab, um die aktuellen fehlerhaften Instanzen des gerade überwachten Dienstes zu finden, und ruft einen Hook zum Aktualisieren / Herstellen von Verbindungen zu ihnen auf. Wie Sie in Abbildung 1 sehen können, versuchte jeder Dienst aufgrund der hohen Häufigkeit von Überwachungsauslösern, die Verbindung zum Zieldienst zu oft zu aktualisieren.

Das war ein großes Problem.
Quelle

Als wir dieses Problem beobachteten, führten wir Consul Server v0.7.0 und einige Agenten mit höheren Versionen wie v0.9.3, v1.0.5 und v1.4.0 aus. Nachdem wir den Quellcode von Consul durchgesehen hatten, frühere Ausgaben und öffentliche Mailinglisten, stellten wir fest, dass die einzige Lösung darin bestand, unsere Consul-Version von v0.7.0 auf mindestens v1.0.7 zu aktualisieren.

Das Problem wurde behoben. (Siehe Abbildung 2)
Abbildung 2: Drop-in-Watch-Durchsatz nach dem Upgrade von Consul auf Version 1.4.0

Abbildung 2 zeigt dasselbe APM-Dashboard nach einem Consul-Upgrade. Dies zeigt einen Rückgang des Watch-Durchsatzes auf nahezu Null, wenn der Service vollständig funktioniert. Dies ist erwartetes Verhalten.

Was war das Problem?

Um zu verstehen, was genau in den letzten Versionen von Consul behoben wurde, beginnen wir zuerst mit den Grundlagen.

Wenn Sie den vorherigen Beitrag zu Consul Watches gelesen haben, sollten Sie mit dem Konzept des X-Consul-Index-Header-Werts vertraut sein. Wir beobachteten, dass der Wert dieses X-Consul-Index-Headers in unserem Consul-Cluster kontinuierlich anstieg, ohne dass sich in den nachgelagerten Diensten ein Statuswechsel ergab. Dieser ständig steigende Wert des X-Consul-Index in jeder Blockierungsabfrage während der Zustandsprüfung führte dazu, dass Uhren in regelmäßigen Abständen ausgelöst wurden (ohne dass sich der Zustand des Dienstes geändert hat). Das brachte uns zu folgender Frage:

Was kann dazu führen, dass sich der X-Consul-Index oder der changeIndex häufig im Consul-Cluster ändert?

Idealerweise sollte modifyIndex sich nur dann ändern, wenn ein Dienst sich selbst registriert oder abmeldet oder wenn die Zustandsüberprüfung durch einen lokalen Agenten eine Änderung seines Status feststellt. Anschließend übermittelt der Agent diesen neuen Status per RPC an den Consul-Server. (Weitere Informationen finden Sie unter Architektur von Konsul). Abgesehen von diesen Kernoperationen führt Consul auch regelmäßig Entropie durch.

Kurz gesagt, Anti-Entropie ist der Prozess, in dem der Agent seinen lokalen Status regelmäßig mit dem Katalogstatus des Servers synchronisiert, sodass der Katalog synchron bleibt.

Während dieser lokalen Statussynchronisierung holt der auf einem bestimmten Knoten ausgeführte Consul-Agent alle auf diesem Knoten registrierten Dienste und Prüfungen aus dem Serverkatalog (verwendet / v1 / catalog / node / und / v1 / health / node) / ). Anschließend holt er alle Dienste und Überprüfungen von lokalen Agenten ab (verwendet / v1 / agent / services und / v1 / agent / checks). Sobald es beides hat, vergleicht es sie anhand ihrer jeweiligen Ausgänge.

In diesem Vergleich wird die Gleichheit der folgenden Felder ServiceID, ServiceName, CheckName, CheckStatus, CheckOutput und ServiceTags geprüft. Es ist wichtig zu beachten, dass hier nicht nur die Ausgabe des CheckStatus-Feldes betrachtet wird, sondern alle diese Felder zum Vergleich auf Gleichheit. Wenn alle übereinstimmen, ruft der Server den lokalen Status nicht auf. Andernfalls ruft es den Consul-Server zur Synchronisierung der Überprüfung auf, indem er einen API-Aufruf an / catalog / register mit dem Anforderungshauptteil als Kontrollfelder des lokalen Agenten ausführt.

Wenn dieser Gleichheitsvergleich nun bei jedem Anti-Entropie-Lauf fehlschlägt, erhält der Consul-Server jedes Mal einen Schreibvorgang für diesen bestimmten Dienst und wendet ihn auf das Raft-Protokoll an. Dadurch wird der Wert des Felds "modifyIndex" in der API-Antwort erhöht, wenn jemand anschließend / v1 / catalog / service aufruft.

Diese Schreibvorgänge, die sich in ihren Statusänderungen nicht unterscheiden, werden im Consul-Cluster als "idempotente Schreibvorgänge" bezeichnet. Aus diesem Grund behaupten alle APIs zum Blockieren von Abfragen nicht, dass jedes Mal, wenn Sie eine API aufrufen, Sie garantiert eine andere Ausgabe erhalten. Es kann sogar dieselbe Ausgabe sein, jedoch mit einem anderen X-Consul-Index-Header-Wert.

Weitere Informationen hierzu finden Sie in Referenz [1], [2], [3].

Tiefer Graben

Der nächste Schritt beim Debugging bestand also darin, herauszufinden, warum die Gleichheitsprüfung bei jedem Anti-Entropiezyklus fehlgeschlagen ist. Nachdem wir den Quellcode von Consul durchgingen und frühere Problemprotokolle auf Github durchgingen, folgerten wir, dass es einen Fehler gab, aufgrund dessen Consul das Speichern von ServiceTags bei Agentenstatusprüfungen nicht unterstützte. Daher stimmten die Katalogprüfungsausgabe und die Agentenprüfungsausgabe während jedes Anti-Entropie-Zyklus nicht überein. Dies war darauf zurückzuführen, dass bei der Statusüberprüfung im Katalog alle ServiceTags während der Serviceregistrierung hinzugefügt wurden, die Prüfungen des lokalen Agenten auf diesem Knoten jedoch nicht. Dies führte dazu, dass der Consul-Agent seinen lokalen Status während jedes Entropiezyklus synchronisierte, was zu vielen Idempotent-Schreibvorgängen für diesen Dienst führte. Dieses Problem wurde in Version 1.0.5 als Teil dieser PR für den Bugfix behoben.

Wenn v1.0.5 das Problem behoben hat, warum zu v1.0.7 wechseln? ‍♀

In den älteren Implementierungen von Consul hatte die Floßindizierung ein bestimmtes Design. Ich werde es an einem Beispiel eines Consul-Clusters erläutern, der zwei Dienste namens service-A und service-B hat. Nehmen wir an, der Status / die Prüfungen von Service-A werden geändert / synchronisiert und der Status / Checks von Service-B nicht. Selbst dann hätte die API-Antwort von / v1 / catalog / service / service-B den X-Consul-Index-Header-Wert, der gleich dem modifyIndex von Service-A ist.

Einfach ausgedrückt: Der X-Consul-Index-Header war nicht dienstspezifisch. Dies war der Index, an dem ein Dienst im Cluster zuletzt im Floßprotokoll geändert wurde. Eine einzelne oder eine falsch konfigurierte Dienstprüfung in einem Cluster würde also dazu führen, dass alle Uhren aufgeweckt werden, da durch das Schreiben in den ModifyIndex eines flappy-Dienstes der Wert des X-Consul-Index-Headers an jedem anderen Katalog-Service-Endpunkt in der Überwachungsschleife erhöht wird .

Dieser Fehler wurde in Version 1.0.7 behoben. Daher mussten wir auf Agent und Server ein Upgrade auf Version 1.0.7 durchführen, da diese Logik des Bestückens des X-Consul-Index in den Antwortheadern vom Server ausgeführt wird.

Falltagebuch

Aufgrund unserer Erfahrung mit Consul haben wir festgestellt, dass sich Consul ziemlich schnell ändert und bei Versions-Upgrades häufig Probleme auftreten. Allerdings ist die Community mit den notwendigen Korrekturen proaktiv und erwähnt, dass Änderungen in den Upgrade-Hinweisen vorgenommen wurden.

Hier sind einige Dinge, die Sie bei der Verwendung von Consul beachten sollten:

1. Stellen Sie sicher, dass Sie über eine geeignete Automatisierung verfügen, um Consul-Cluster in der Produktion aktualisieren zu können.
2. Lesen Sie vor dem Upgrade immer das Release-Änderungsprotokoll, und stellen Sie sicher, dass Sie wissen, was neu ist und was veraltet oder entfernt wird.

Detaillierte Anweisungen zum Upgrade von Consul finden Sie hier.

Verweise:

  1. Was ist ein idempotentes Schreiben und wann passiert es?
  2. Nebenwirkungen von idempotentem Schreiben
  3. Consul-Quellcode-Funktion updateSyncState wird während der Anti-Entropie verwendet
  4. Konsulblockierungsabfragen
  5. Hinweise zum Upgrade des Konsuls
  6. Anweisungen zum Upgrade von Consul
  7. Was ist Service Mesh und warum brauchen Sie eines?

GOJEK betreibt einen der größten JRuby-, Java- und Go-Cluster in Südostasien, verarbeitet monatlich über 100 Millionen Transaktionen und arbeitet mit 2 Millionen Treiberpartnern zusammen. Wir verändern die Dynamik von On-Demand-Plattformen, verbessern die Lebensqualität und schaffen soziale Auswirkungen. Wir sind auch auf der Suche nach mehr Talent, um schwierige technische Probleme zu lösen. Wollen Sie versuchen, die Waage in Begleitung der Besten der Branche zu meistern? Ihre Reise beginnt bei gojek.jobs. Lass uns krachen ️

gojek.jobs

Siehe auch

Sie sagtenVerbessern Sie die Wiederverwendbarkeit von Code mit dem Render Prop-Muster von React