Skalierungsrisiken steuern

Die Google-Infrastruktur ist auf hohe Skalierbarkeit und maximale Flexibilität ausgelegt, d. h. auf den meisten Ebenen ist selbst eine Anpassung an massive Trafficanstiege möglich. Ein wesentliches Designmuster für die Realisierung dieser Zielsetzung sind adaptive Ebenen. Dabei handelt es sich um Infrastrukturkomponenten, die die Last auf der Basis von Trafficmustern dynamisch neu zuordnen. Diese Anpassung nimmt jedoch eine gewisse Zeit in Anspruch. Da Cloud Tasks die Weiterleitung sehr großer Trafficvolumen ermöglicht, kann es zu Situationen kommen, in denen der Traffic schneller zunimmt, als die Infrastruktur angepasst werden kann. Dies führt zu Risiken für die Produktion.

Überblick

In diesem Dokument werden Best Practices erläutert, die eine hohe Leistung von Cloud Tasks für Warteschlangen mit hohem Traffic gewährleisten. In einer Warteschlange mit hoher TPS-Rate (= Tasks per Second) werden mindestens 500 Aufgaben pro Sekunde (TPS) erstellt oder weitergeleitet. Eine Warteschlangengruppe mit hoher TPS-Rate ist ein zusammenhängender Satz Warteschlangen, z. B. [queue0001, queue0002, …, queue0099]. In diesem Satz werden insgesamt mindestens 2.000 Aufgaben erstellt oder weitergeleitet. Der Verlauf der TPS-Raten einer Warteschlange oder einer Gruppe von Warteschlangen kann über Stackdriver-Messwerte oder mit api/request_count für CreateTask-Vorgänge bzw. mit queue/task_attempt_count für Aufgabenversuche eingesehen werden. Warteschlangen und Warteschlangengruppen mit hohem Traffic sind anfällig für Fehler, die den beiden folgenden allgemeinen Kategorien angehören:

Eine Warteschlangenüberlastung tritt auf, wenn die Erstellung von Aufgaben und deren Weiterleitung zu einer einzelnen Warteschlange oder einer Warteschlangengruppe schneller zunimmt, als die Infrastruktur der Warteschlange verarbeiten kann. Ähnlich verhält es sich bei einer Zielüberlastung. In diesem Fall verursacht die Rate, mit der Aufgaben weitergeleitet werden, Trafficspitzen in der nachgelagerten Infrastruktur des Ziels. In beiden Fällen empfehlen wir ein 500/50/5-Muster. Dies bedeutet, dass der Traffic bei einer Skalierung oberhalb von 500 TPS nicht um mehr als 50 % pro 5 Minuten erhöht werden darf. In diesem Dokument werden verschiedene Szenarien mit potenziellen Skalierungsrisiken und Beispiele für die Anwendung dieses Musters vorgestellt.

Warteschlangenüberlastung

Jeder plötzliche Traffic-Anstieg kann zu einer Überlastung von Warteschlangen oder Warteschlangengruppen führen. In den betroffenen Warteschlangen ist möglicherweise Folgendes zu beobachten:

  • Erhöhte Latenz bei der Aufgabenerstellung
  • Erhöhte Fehlerrate bei der Aufgabenerstellung
  • Geringere Weiterleitungsrate

Wenn Sie diese Probleme vermeiden möchten, empfehlen wir die Implementierung von Kontrollmechanismen für Fälle, in denen es zu einem sprunghaften Anstieg der Erstellungs- oder Weiterleitungsrate einer Warteschlange oder Warteschlangengruppe kommen kann. Wir empfehlen einen Höchstwert von 500 Vorgängen pro Sekunde bei einer kalten Warteschlange oder Warteschlangengruppe. Danach kann der Traffic alle 5 Minuten um 50 % erhöht werden. Theoretisch können Sie den Traffic mit diesem Erhöhungsplan nach 90 Minuten auf 740.000 Vorgänge ausweiten. Dies kann in einer Reihe von Situationen Anwendung finden.

Beispiele:

  • Beim Implementieren neuer Funktionen, die in großem Umfang Cloud Tasks nutzen
  • Beim Verschieben von Traffic zwischen Warteschlangen
  • Bei der gleichmäßigen Verteilung der Traffic-Last auf mehr oder weniger Warteschlangen
  • Beim Ausführen von Batchjobs, die eine große Anzahl von Aufgaben einfügen

Wenden Sie in diesen und anderen Fällen das 500/50/5-Muster an.

Trafficaufteilung von App Engine verwenden

Wenn die Aufgaben in einer App Engine-Anwendung erstellt werden, können Sie mithilfe der Trafficaufteilung von App Engine (Standard/Flex) den Trafficanstieg ausgleichen. Traffic lässt sich auf die Standard- und die Flex-Version aufteilen. Dadurch können Anfragen, die eine Anpassung der Rate erfordern, zeitversetzt bereitgestellt werden, um die Funktionsfähigkeit der Warteschlangen zu gewährleisten. Beispiel: Angenommen, der Traffic soll auf eine gerade erweiterte Warteschlangengruppe aufgeteilt werden. Dabei ist [queue0000, queue0199] eine Warteschlangensequenz mit hoher TPS-Rate, die bei Lastspitzen insgesamt 100.000 Aufgabenerstellungen pro Sekunde empfängt.

Die neue Warteschlangensequenz ist [queue0200, queue0399]. Nachdem der gesamte Traffic verschoben wurde, hat sich die Anzahl der Warteschlangen in der Sequenz verdoppelt und der neue Warteschlangenbereich empfängt 50 % des gesamten Traffics der Sequenz.

Steigern Sie beim Bereitstellen der Version, die die Anzahl der Warteschlangen erhöht, mithilfe der Traffic-Aufteilung allmählich den Traffic für die neue Version (und damit die neuen Warteschlangen):

  • Beginnen Sie damit, 1 % des Traffics in die neue Version zu verschieben. 50 % von 1 % von 100.000 TPS ergeben beispielsweise 500 TPS für die neue Warteschlangengruppe.
  • Erhöhen Sie den an die neue Version gesendeten Traffic alle 5 Minuten um 50 %, wie in der folgenden Tabelle angegeben:
Minuten seit Bereitstellungsbeginn % des in die neue Version verschobenen Gesamt-Traffics % des Gesamt-Traffics für die neuen Warteschlangen % des Gesamt-Traffics für die alten Warteschlangen
0 1,0 0,5 99,5
5 1,5 0,75 99,25
10 2,3 1,15 98,85
15 3,4 1,7 98,3
20 5,1 2,55 97,45
25 7,6 3,8 96,2
30 11,4 5,7 94,3
35 17,1 8,55 91,45
40 25,6 12,8 87,2
45 38,4 19,2 80,8
50 57,7 28,85 71,15
55 86,5 43,25 56,75
60 100 50 50

Releasebedingte Traffic-Spitzen

Wenn Sie einen Release implementieren, der den Traffic an eine Warteschlange oder Warteschlangengruppe signifikant erhöht, ist auch hierbei der schrittweise Rollout ein wichtiger Mechanismus zum Ausgleichen der Anstiege. Stellen Sie Ihre Instanzen nach und nach bereit, sodass bei der Implementierung zuerst nicht mehr als insgesamt 500 Vorgänge an die neuen Warteschlangen gesendet werden und dieser Wert höchstens um 50 % pro 5 Minuten erhöht wird.

Neue Warteschlangen oder Warteschlangengruppen mit hoher TPS-Rate

Neu erstellte Warteschlangen sind besonders anfällig. Dabei sind Warteschlangengruppen wie [queue0000, queue0001queue0199] während der anfänglichen Rollout-Phasen ebenso gefährdet wie einzelne Warteschlangen. Für solche Warteschlangen ist der schrittweise Rollout eine wichtige Strategie. Starten Sie neue oder aktualisierte Dienste, die Warteschlangen oder Warteschlangengruppen mit hohen TPS-Raten generieren, in mehreren Phasen, sodass die Anfangslast unter 500 TPS liegt und Erhöhungen um höchstens 50 % in Abständen von 5 oder mehr Minuten erfolgen.

Kürzlich erweiterte Warteschlangengruppen

Wenn Sie die Gesamtkapazität einer Warteschlangengruppe erhöhen, zum Beispiel durch Erweitern von [queue0000-queue0199] auf [queue0000-queue0399], sollten Sie nach dem 500/50/5-Muster vorgehen. Dabei ist zu beachten, dass sich neue Warteschlangengruppen bei Rollout-Verfahren wie einzelne Warteschlangen verhalten. Wenden Sie also das 500/50/5-Muster auf die neue Gruppe als Ganzes und nicht nur auf einzelne Warteschlangen der Gruppe an. Auch bei diesen Erweiterungen von Warteschlangengruppen spielt der schrittweise Rollout eine wichtige Rolle. Wenn der Traffic von App Engine ausgeht, können Sie die Trafficaufteilung anwenden (siehe Releasebedingte Trafficspitzen). Wenn Sie Ihren Dienst migrieren und den hinzugekommenen Warteschlangen Aufgaben hinzufügen, stellen Sie die Instanzen nach und nach bereit, sodass beim ersten Starten nicht mehr als insgesamt 500 Vorgänge an die neuen Warteschlangen gesendet werden und dieser Wert um höchstens 50 % pro 5 Minuten erhöht wird.

Warteschlangengruppen im Notfall erweitern

Manchmal kann die Erweiterung einer vorhandenen Warteschlangengruppe erforderlich werden. Beispielsweise, wenn zu erwarten ist, dass der Warteschlangengruppe Aufgaben schneller hinzugefügt werden, als sie weitergeleitet werden können. Wenn die Namen der neuen Warteschlangen bei lexikografischer Sortierung gleichmäßig in die Liste der vorhandenen Warteschlangen eingeordnet werden, kann der Traffic sofort an diese Warteschlangen gesendet werden. Allerdings muss der Anteil der neuen eingefügten Warteschlangen unter 50 % liegen und der Traffic darf für eine einzelne Warteschlange 500 TPS nicht überschreiten Diese Methode stellt eine Alternative zu den Methoden der Trafficaufteilung und des schrittweisen Rollouts dar, die in den vorangegangenen Abschnitten beschrieben wurden.

Diese Art der verschachtelten Namensgebung kann erreicht werden, indem ein Suffix an Warteschlangen angehängt wird, die mit geraden Zahlen enden. Beispiel: Wenn 200 Warteschlangen vorhanden sind [queue0000-queue0199] und 100 neue Warteschlangen erstellt werden sollen, wählen Sie [queue0000a, queue0002a, queue0004aqueue0198a] anstelle von [queue0200-queue0299] als neue Warteschlangennamen aus.

Wenn eine weitere Erhöhung nötig ist, können Sie alle 5 Minuten bis zu 50 % mehr Warteschlangen verschachteln.

Umfangreiche Aufgaben/Batchjobs in Warteschlangen stellen

Wenn eine sehr große Anzahl von Aufgaben (zum Beispiel Millionen oder Milliarden) hinzugefügt werden muss, kann ein Doppelinjektionsmuster hilfreich sein. Statt Aufgaben aus einem einzigen Job zu erstellen, verwenden Sie eine Injektorwarteschlange. Jede Aufgabe, die der Injektorwarteschlange hinzugefügt wird, fügt der gewünschten Warteschlange oder Warteschlangengruppe per Fanout 100 Aufgaben hinzu. Die Injektorwarteschlange kann dynamisch beschleunigt werden und beispielsweise mit 5 TPS beginnen und alle 5 Minuten um 50 % ansteigen.

Benannte Aufgaben

Wenn Sie eine neue Aufgabe erstellen, ordnet Cloud Tasks der Aufgabe standardmäßig einen eindeutigen Namen zu. Mit dem Parameter name können Sie einen eigenen Namen für eine Aufgabe zuordnen. Dies führt jedoch zu signifikanten Leistungseinbußen sowie zu erhöhten Latenzen und möglicherweise zu höheren Fehlerraten für die benannten Aufgaben. Diese Nachteile können noch erheblich zunehmen, wenn Aufgaben sequenziell benannt werden, beispielsweise mit Zeitstempeln. Wir empfehlen daher beim Zuordnen eigener Namen die Verwendung eines wohl überlegten Präfixes für Aufgabennamen (z. B. eines Hash-Werts des Inhalts). Weitere Informationen zum Benennen von Aufgaben finden Sie in der Dokumentation.

Zielüberlastung

Falls die Weiterleitungen aus einer Warteschlange in einem kurzen Zeitraum drastisch ansteigen, kann Cloud Tasks andere von Ihnen genutzte Dienste wie App Engine und Datastore überlasten und Ihre Netzwerknutzung heraufsetzen. Die Überlastung dieser Dienste kann auftreten, wenn sich ein Rückstand von Aufgaben angesammelt hat und das Pausieren der entsprechenden Warteschlangen aufgehoben wird. Als Gegenmaßnahme empfiehlt sich dasselbe 500/50/5-Muster, das auch für die Warteschlangenüberlastung vorgeschlagen wurde: Wenn eine Warteschlange mehr als 500 TPS weiterleitet, erhöhen Sie den von einer Warteschlange ausgelösten Traffic um maximal 50 % alle 5 Minuten. Nutzen Sie die Stackdriver-Messwerte, um die Traffic-Anstiege proaktiv zu überwachen. Außerdem können Sie mithilfe von Stackdriver-Benachrichtigungen potenziell gefährliche Situationen erkennen.

Angehaltene Warteschlangen mit hoher TPS-Rate fortsetzen

Wenn Sie das Pausieren einer Warteschlange oder Warteschlangensequenz aufheben bzw. diese reaktivieren, wird die Weiterleitung von Aufgaben fortgesetzt. Falls die betreffende Warteschlange viele Aufgaben enthält, kann ihre Weiterleitungsrate sprunghaft von 0 TPS auf die volle Kapazität der Warteschlange ansteigen. Gehen Sie bei der Erhöhung daher schrittweise vor, indem Sie Warteschlangen gestaffelt fortsetzen oder ihre Weiterleitungsraten mit dem Cloud Tasks-Flag maxDispatchesPerSecond steuern.

Im Bulk geplante Aufgaben

Eine große Anzahl von Aufgaben, deren Weiterleitung für denselben Zeitpunkt geplant ist, kann ebenfalls zu einer Zielüberlastung führen. Wenn Sie also viele Aufgaben gleichzeitig starten müssen, sollten Sie gegebenenfalls mithilfe der Steuermechanismen für Warteschlangenraten die Weiterleitungsrate schrittweise erhöhen oder die Zielkapazität vorab explizit hochfahren.

Erhöhter Fanout

Die Aktualisierung von Diensten, die über Cloud Tasks ausgeführt werden, und die damit einhergehende Erhöhung von Remoteaufrufen können ebenfalls Produktionsrisiken bergen. Beispiel: Angenommen, die Aufgaben in einer Warteschlange mit hoher TPS-Rate rufen den Handler /task-foo auf. Durch einen neuen Release kann sich dann der Traffic durch den Aufruf von /task-foo deutlich erhöhen, etwa wenn dem Handler dadurch mehrere umfangreiche Datastore-Aufrufe hinzugefügt werden. Das Endergebnis eines solchen Release wäre ein massiver Anstieg des Datastore-Traffics, der sich unmittelbar auf die Höhe des Nutzertraffics auswirkt. Verwenden Sie zum Verarbeiten der Erhöhung einen schrittweisen Rollout oder die Traffic-Aufteilung.

Neuversuche

Beim Aufrufen der Task Queue API kann die Ausführung Ihres Codes bei einem Fehler noch einmal versucht werden. Wenn jedoch ein erheblicher Teil von Anfragen aufgrund von serverseitigen Fehlern fehlschlägt, besteht die Gefahr, dass eine hohe Wiederholungsrate die Warteschlangen noch mehr überlastet und dazu führt, dass der Dienst erst nach einer längeren Zeit wieder genutzt werden kann. Daher empfehlen wir, den Umfang des ausgehenden Traffics zu begrenzen, wenn der Client feststellt, dass ein erheblicher Teil der Anfragen aufgrund von serverseitigen Fehlern fehlschlägt. Dazu können Sie z. B. den Adaptive-Throttling-Algorithmus verwenden, der im SRE-Handbuch im Kapitel Umgang mit Überlastungen beschrieben wird. In den gRPC-Clientbibliotheken von Google ist eine Variante des Adaptive-Throttling-Algorithmus implementiert.