Wie vermeide ich "Wiederholungsstürme" in verteilten Diensten?

10

Ein "Wiederholungssturm" wird verursacht, wenn Clients so konfiguriert sind, dass sie eine festgelegte Anzahl von Malen wiederholen, bevor sie aufgeben. Eine Wiederholungsrichtlinie ist erforderlich, da im normalen Betrieb eines Dienstes Paketverluste auftreten.

Nehmen Sie dieses Beispiel:

Beispielarchitektur

Wenn beispielsweise die Dienste insgesamt so skaliert würden, dass sie 80.000 Anforderungen pro Sekunde unterstützen und mit etwa 80% der Kapazität ausgeführt werden, würde ein Anstieg des Datenverkehrs, der dazu führte, dass der Dienst 101.000 Anforderungen pro Sekunde empfing, dazu führen, dass 1.000 dieser Anforderungen fehlschlagen.

Wenn die Wiederholungsrichtlinien aktiviert werden, erhalten Sie mehr als 1.000 Anfragen, je nachdem, wo der Fehler festgestellt wurde, wodurch der Dienst insgesamt auf 102.000 Anfragen pro Sekunde erhöht wird. Von dort aus geht Ihr Dienst in eine Todesspirale über, die die Anzahl verdoppelt von fehlgeschlagenen Anfragen jede Sekunde.

Abgesehen von einer massiven Überbereitstellung von Diensten über die geplante Spitzentransaktion hinaus, die ineffizient wäre. Welche Strategien können Sie anwenden, um "Wiederholungsstürme" zu vermeiden?

Richard Slater
quelle
Wenn 100 kQPS 80% der Kapazität ausmachen, sollten 101 kQPS nicht zu 1.000 Fehlern führen, sondern zu null Fehlern - ist das nicht der Punkt der Überprovisionierung?
Adrian
@Adrian Ihr Recht, es war ein erfundenes Beispiel, um den Punkt zu erklären - ich habe versucht, reduktiv genug zu sein, um meinen Punkt klar zu machen, ohne übermäßig abstrakt zu sein. Ich habe die "Skalierung auf Unterstützung 100.000" auf "Skaliert auf Unterstützung 80.000" korrigiert.
Richard Slater

Antworten:

7

Es hängt davon ab, was Sie vermeiden möchten.

Wenn Sie versuchen, eine Dienstunterbrechung von etwas zu vermeiden, das ein wirklich kritischer Dienst ist (ich denke in Bezug auf "Menschen werden sterben, wenn mein API-Aufruf nicht angemessen bedient wird"), müssen Sie nur die enormen Ineffizienzen budgetieren, die kommen von weit über die Bereitstellung dedizierter Ressourcen. Und ja, sie müssen dediziert sein, nichts davon erlaubt Verkehrsspitzen, mehrere Dienstspitzen würden somit einen Ausfall verursachen.

In dem weitaus wahrscheinlicheren Szenario, dass Ihr Dienst ausfällt, können Sie das Problem sowohl auf Client- als auch auf Serverseite lösen. Obwohl es erwähnenswert ist, dass es logisch unmöglich ist, das Problem von zu viel Verkehr tatsächlich zu lösen, können Sie ohne Verarbeitung des Verkehrs (der Ressourcen verbraucht) nicht wissen, ob es sich um eine Wiederholung handelt, ob es sich um eine Wiederholung für eine Anforderung handelt, die erfolgreich war, aber falsch behandelt wurde vom Client, wenn es sich um ein DDOS usw. handelt. Sie können jedoch die Auswirkungen abschwächen.

Schreiben Sie im Client-Code eine sinnvolle Wiederholungslogik, die eine Obergrenze und einen Mechanismus für ein ordnungsgemäßes Versagen aufweist. Auf diese Weise halten Sie Ihre Benutzer nicht in eine Endlosschleife fehlgeschlagener Anfragen und geben ihnen nur einen Fehler, der sie auffordert, alles zu versuchen, was sie gerade getan haben.

Für Ihre serverseitige Infrastruktur besteht die einfachste Lösung darin, zu drosseln. Harte Grenzen für Anforderungen, insbesondere wenn Sie versuchen können, sie basierend auf Ihrem spezifischen Anwendungsfall logisch zu verbreiten (z. B. wenn ein zentraler Dienst einige schwierige Entscheidungen trifft, möchten Sie damit beginnen, geografisch entfernte Anforderungen zu blockieren, was dazu führen kann, dass Threads hängen bleiben Serverseitig? Oder möchten Sie Ihren unvermeidlichen, aber geringfügigen Ausfall gleichmäßig verteilen? usw.) Es läuft im Grunde darauf hinaus, dass die absichtliche Rückgabe eines 503 von einem Gateway um einiges billiger ist, als die Anfrage durchzulassen und einen 504 zu senden wie auch immer. Erzwingen Sie grundsätzlich, dass sich Kunden basierend auf dem, was Sie derzeit bereitstellen können, verhalten und die richtigen Antworten bereitstellen, damit Kunden angemessen reagieren können.

hvindin
quelle
5

Eine Möglichkeit, diese Wiederholungsstürme zu verhindern, ist die Verwendung von Backoff-Mechanismen.

Aus dem Abschnitt " Backoff bei Wiederholung wiederholen " des Handbuchs " Google App Engine- Design für Skalierung" :

Ihr Code kann bei einem Fehler erneut versucht werden, unabhängig davon, ob Sie einen Dienst wie Cloud Datastore oder einen externen Dienst über URL Fetch oder die Socket-API aufrufen. In diesen Fällen sollten Sie immer eine randomisierte exponentielle Backoff-Richtlinie implementieren, um das Problem der donnernden Herde zu vermeiden . Sie sollten auch die Gesamtzahl der Wiederholungsversuche begrenzen und Fehler behandeln, nachdem das maximale Wiederholungslimit erreicht wurde.

In den meisten GAE-APIs sind solche Backoff-Mechanismen / -Richtlinien bereits standardmäßig aktiviert.

Dan Cornilescu
quelle
Dank der Implementierung von Backoff-Mechanismen ist dies ein guter Rat. Normalerweise entscheide ich mich für ein konfigurierbares exponentielles Backoff mithilfe des Anwendungsblocks für die Behandlung vorübergehender Fehler . Aufgrund von mehr als 5 Jahren Betriebserfahrung beim Betrieb von Hyper-Scale-Anwendungen in Azure treten "Wiederholungsstürme" auch bei exponentiellen Backoffs immer noch ziemlich häufig auf - ich habe nie eine praktikable Strategie gefunden, um sie zu vermeiden.
Richard Slater