Fehlerbehebung bei erhöhter Latenz in App Engine-Anwendungen

In vielen Fällen führt eine erhöhte Latenz in Ihrer Anwendung letztendlich zu 5xx-Serverfehlern. Da die Ursache für den Fehler und die Latenzspitzen möglicherweise dieselbe ist, können Sie die folgenden Strategien zur Behebung von Latenzproblemen anwenden:

  1. Latenzproblem eingrenzen
  2. Ursache ermitteln
  3. Fehlerbehebung

Latenzproblem eingrenzen

Definieren Sie den Umfang des Problems, indem Sie sich die folgenden Fragen stellen:

  • Auf welche Anwendungen, Dienste und Versionen wirkt sich dieses Problem aus?
  • Auf welche spezifischen Endpunkte des Dienstes wirkt sich dieses Problem aus?
  • Wirkt sich dies auf alle Kunden weltweit oder auf eine bestimmte Teilmenge von Kunden aus?
  • Wie lauten Start und Ende des Vorfalls? Geben Sie gegebenenfalls die Zeitzone an.
  • Welche Fehler treten auf?
  • Was ist das beobachtete Latenzdelta, das normalerweise als Erhöhung bei einem bestimmten Perzentil angegeben wird? Beispiel: die Latenz war beim 90. Perzentil um 2 Sekunden erhöht.
  • Wie haben Sie die Latenz gemessen? Wurde die Anfrage insbesondere auf dem Client gemessen oder ist sie in Cloud Logging oder in den Cloud Monitoring-Latenzdaten sichtbar, die von der App Engine-Bereitstellungsinfrastruktur bereitgestellt werden?
  • Welche Abhängigkeiten hat Ihr Dienst und hat es Vorfälle mit diesen gegeben?
  • Haben Sie vor Kurzem Code-, Konfigurations- oder Arbeitslaständerungen vorgenommen, die dieses Problem ausgelöst haben könnten?

Ein Dienst kann über ein eigenes benutzerdefiniertes Monitoring und Logging verfügen, mit dem Sie den Problembereich eingrenzen können. Wenn Sie den Umfang des Problems eingrenzen, werden Sie zur wahrscheinlichen Ursache geführt und können die nächsten Schritte zur Fehlerbehebung ermitteln.

Ursache ermitteln

Bestimmen Sie, welche Komponente im Anfragepfad hauptsächlich die Latenz oder Fehler verursacht. Die Hauptkomponenten im Anfragepfad sind:

Client -> Internet -> Google Front End (GFE) -> App Engine-Bereitstellungsinfrastruktur -> Dienstinstanz

Wenn die vorherigen Informationen nicht auf die Fehlerquelle verweisen, wenden Sie die folgenden Strategien an, während Sie den Zustand und die Leistung Ihrer Dienstinstanz prüfen:

  1. Überwachen Sie die App Engine-Anfrageprotokolle. Wenn Sie HTTP-Statuscodefehler oder eine erhöhte Latenz in diesen Logs sehen, liegt das Problem wahrscheinlich an der Instanz, auf der Ihr Dienst ausgeführt wird.

  2. Wenn die Anzahl der Dienstinstanzen nicht an die Verkehrszahlen angepasst wurde, sind Ihre Instanzen möglicherweise überlastet, was zu mehr Fehlern und Latenz führt.

  3. Wenn in Cloud Monitoring häufige Fehler oder hohe Latenz auftreten, liegt das Problem möglicherweise vor dem Load Balancer, der die App Engine-Messwerte aufzeichnet. In den meisten Fällen weist dies auf ein Problem in den Dienstinstanzen hin.

  4. Wenn Sie eine hohe Latenz oder Fehler in den Monitoring-Messwerten sehen, aber nicht in den Anfragelogs, weist dies entweder auf einen Fehler beim Load Balancing oder auf einen schwerwiegenden Instanzfehler hin, der den Load Balancer daran hindert, Anfragen weiterzuleiten. Um zwischen diesen Fällen zu unterscheiden, sehen Sie sich die Anfrageprotokolle an, bevor der Vorfall beginnt. Wenn die Anfragelogs vor dem Fehler eine zunehmende Latenz zeigen, bedeutet dies, dass die Anwendungsinstanzen selbst versagen, bevor der Load-Balancer keine Anfragen mehr an sie weiterleitet.

Fehlerbehebung

In diesem Abschnitt werden Strategien zur Fehlerbehebung bei erhöhten Latenzproblemen aufgrund der folgenden Komponenten im Anfragepfad beschrieben:

  1. Internet
  2. Google Front End (GFE)
  3. App Engine-Bereitstellungsinfrastruktur
  4. Anwendungsinstanz
  5. Anwendungsabhängigkeiten

Internet

Aufgrund einer schlechten Verbindung oder einer geringeren Bandbreite kann es bei Ihrer Anwendung zu Latenzproblemen kommen.

Schlechte Internetverbindung

Führen Sie den folgenden Befehl auf Ihrem Client aus, um festzustellen, ob das Problem eine schlechte Internetverbindung ist:

$ curl -s -o /dev/null -w '%{time_connect}\n' <hostname>

Der Wert für time_connect stellt die Latenz der Clientverbindung zum nächsten Google Front End dar. Bei langsamen Verbindungen können Sie mithilfe von traceroute weitere Fehler beheben, um festzustellen, welcher Hop im Netzwerk die Verzögerung verursacht.

Tests von Clients an verschiedenen geografischen Standorten ausführen Die App Engine leitet Anfragen automatisch an das nächstgelegene Google-Rechenzentrum weiter, was je nach Standort des Clients variiert.

Niedrige Bandbreite

Die Anwendung reagiert möglicherweise schnell, aber Netzwerkengpässe verhindern, dass die App Engine-Bereitstellungsinfrastruktur Pakete schnell über das Netzwerk sendet, was die Antworten verlangsamt.

Google Front End (GFE)

Bei Ihrer Anwendung können aufgrund von falschem Routing, parallelen Anfragen, die von HTTP/2-Clients gesendet werden, oder der Beendigung von SSL-Verbindungen Latenzprobleme auftreten.

Client-IP einer geografischen Region zuordnen

Google löst den Hostnamen der App Engine-Anwendung auf Grundlage der Client-IP-Adresse, die bei der DNS-Suche verwendet wird, zum nächstgelegenen GFE zum Client auf. Wenn der DNS-Resolver des Clients nicht das EDNS0-Protokoll verwendet, leitet Google die Clientanfragen möglicherweise nicht an das nächstgelegene GFE weiter.

HTTP/2-Head-of-Line-Blocking

HTTP/2-Clients, die mehrere Anfragen parallel senden, können aufgrund des Head-of-Line-Blockings im GFE eine erhöhte Latenz aufweisen. Um dieses Problem zu beheben, müssen die Clients das QUIC-Protokoll verwenden.

SSL-Terminierung für benutzerdefinierte Domains

Das GFE beendet möglicherweise die SSL-Verbindung. Wenn Sie eine benutzerdefinierte Domain anstelle einer appspot.com-Domain verwenden, ist für die SSL-Terminierung ein zusätzlicher Hop erforderlich. Dies kann zu Latenzen bei Anwendungen führen, die in einigen Regionen ausgeführt werden. Weitere Informationen finden Sie unter Benutzerdefinierte Domains zuordnen.

App Engine-Bereitstellungsinfrastruktur

Aufgrund von dienstweiten Vorfällen oder automatischer Skalierung kann es zu einer erhöhten Latenz in Ihrer Anwendung kommen.

Dienstweite Vorfälle

Google veröffentlicht Details zu schwerwiegenden dienstweiten Problemen im Dashboard Dienststatus. Google führt jedoch schrittweise Rollouts durch, sodass ein dienstweiter Vorfall wahrscheinlich nicht alle Instanzen gleichzeitig betrifft.

Autoscaling

Die folgenden Autoscaling-Szenarien können zu einer erhöhten Latenz oder zu Fehlern führen:

  • Traffic zu schnell hochskaliert: Beim App Engine-Autoscaling werden Ihre Instanzen möglicherweise nicht so schnell skaliert, wie der Traffic zunimmt, was zu einer vorübergehenden Überlastung führt. In der Regel tritt eine Überlastung auf, wenn der Traffic von einem Computerprogramm und nicht von Endnutzern generiert wird. Um dieses Problem zu beheben, drosseln Sie das System, das den Traffic generiert.

  • Trafficspitzen: Trafficspitzen können zu einer höheren Latenz führen, wenn ein automatisch skalierter Dienst schneller hochskaliert werden muss, als es ohne Beeinträchtigung der Latenz möglich ist. Endnutzer-Traffic verursacht in der Regel keine häufigen Trafficspitzen. Wenn Sie Trafficspitzen feststellen, sollten Sie die Ursache untersuchen. Wenn ein Batchsystem in Intervallen ausgeführt wird, können Sie den Traffic möglicherweise ausgleichen oder andere Skalierungseinstellungen verwenden.

  • Autoscaler-Einstellungen: Der Autoscaler kann anhand der Skalierungsmerkmale Ihres Dienstes konfiguriert werden. Die Skalierungsparameter können sich in den folgenden Szenarien ungünstig entwickeln:

    • Die Skalierungseinstellungen der App Engine-Standardumgebung können zu Latenzen führen, wenn sie zu aggressiv festgelegt sind. Wenn Sie in Ihren Logs Serverantworten mit dem Statuscode 500 und der Meldung „Anfrage wurde abgebrochen, da der Versuch, die Anfrage zu bearbeiten, zu lange gedauert hat“ sehen, wurde das Zeitlimit überschritten, während die Anfrage in der Warteschlange auf eine freie Instanz wartete.

    • Bei manueller Skalierung kann es zu längeren Wartezeiten kommen, auch wenn Sie genügend Instanzen bereitgestellt haben. Wir empfehlen, keine manuelle Skalierung zu verwenden, wenn Ihre Anwendung Endnutzertraffic verarbeitet. Die manuelle Skalierung eignet sich besser für Arbeitslasten wie Aufgabenwarteschlangen.

    • Bei der einfachen Skalierung werden die Kosten auf Kosten der Latenz minimiert. Wir empfehlen, die grundlegende Skalierung nicht für latenzempfindliche Dienste zu verwenden.

    • Die Standardskalierungseinstellung der App Engine bietet eine optimale Latenz für die meisten Dienste. Wenn Sie weiterhin Anfragen mit hoher Wartezeit sehen, geben Sie eine Mindestanzahl von Instanzen an. Wenn Sie die Skalierungseinstellungen zur Minimierung der Kosten optimieren, indem Sie inaktive Instanzen minimieren, besteht die Gefahr, dass Latenzspitzen auftreten, wenn die Last plötzlich ansteigt.

Wir empfehlen Ihnen, die Leistung mit den Standardskalierungseinstellungen zu vergleichen und nach jeder Änderung an diesen Einstellungen eine neue Benchmark auszuführen.

Deployments

Eine erhöhte Latenz kurz nach einer Bereitstellung gibt an, dass Sie vor der Migration des Traffics nicht ausreichend vertikal skaliert haben. Neuere Instanzen haben möglicherweise keine lokalen Caches vorbereitet und können daher langsamer ausgeführt werden als ältere Instanzen.

Stellen Sie keine App Engine-Dienste bereit, die denselben Versionsnamen wie eine vorhandene Dienstversion verwenden, um Latenzspitzen zu vermeiden. Wenn Sie einen vorhandenen Versionsnamen wiederverwenden, können Sie den Traffic nicht langsam zur neuen Version migrieren. Anfragen können langsamer sein, da jede Instanz innerhalb kurzer Zeit von der App Engine neu gestartet wird. Sie müssen die Bereitstellung auch noch einmal ausführen, wenn Sie zur vorherigen Version zurückkehren möchten.

Anwendungsinstanz

In diesem Abschnitt werden die gängigen Strategien beschrieben, die Sie auf Ihre Anwendungsinstanzen und den Quellcode anwenden können, um die Leistung zu optimieren und die Latenz zu verringern.

Anwendungscode

Probleme im Anwendungscode können schwierig zu beheben sein, insbesondere wenn sie sporadisch auftreten oder nicht reproduzierbar sind.

So beheben Sie Probleme:

  • Zur Diagnose von Problemen empfehlen wir, Ihre Anwendung mit Logging, Monitoring und Tracing zu instrumentieren. Sie können auch Cloud Profiler verwenden.

  • Versuchen Sie, das Problem in einer lokalen Entwicklungsumgebung zu reproduzieren. Dadurch können Sie sprachspezifische Debugging-Tools ausführen, die möglicherweise nicht in App Engine ausgeführt werden können.

  • Damit Sie besser verstehen, warum Ihre Anwendung fehlschlägt und welche Engpässe auftreten, können Sie einen Lasttest Ihrer Anwendung ausführen, bis ein Fehler auftritt. Legen Sie eine maximale Anzahl von Instanzen fest und erhöhen Sie dann die Last nach und nach, bis die Anwendung fehlschlägt.

  • Wenn das Latenzproblem mit der Bereitstellung einer neuen Version Ihres Anwendungscodes korreliert, führen Sie ein Rollback durch, um festzustellen, ob die neue Version den Vorfall verursacht hat. Bei einer kontinuierlichen Bereitstellung kann die Häufigkeit der Bereitstellungen so groß sein, dass es schwierig ist, basierend auf der Zeit des Auftretens festzustellen, ob die Bereitstellung den Vorfall verursacht hat.

  • Ihre Anwendung kann Konfigurationseinstellungen in Datastore oder an einem anderen Ort speichern. Erstellen Sie eine Zeitachse mit Konfigurationsänderungen, um zu bestimmen, ob eine dieser Zeilen mit dem erhöhten Latenzwert übereinstimmt.

Arbeitslaständerung

Eine Änderung der Arbeitslast kann zu einer erhöhten Latenz führen. Einige Monitoring-Messwerte, die auf Änderungen der Arbeitslast hinweisen, sind qps, die API-Nutzung und die Latenz. Prüfen Sie auch auf Änderungen bei Anfrage- und Antwortgrößen.

Arbeitsspeicherdruck

Wenn das Monitoring entweder ein Sägezahnmuster in der Speichernutzung oder einen Rückgang der Speichernutzung zeigt, der mit Bereitstellungen korreliert, kann ein Speicherleck die Ursache für Leistungsprobleme sein. Ein Speicherleck kann auch zu einer häufigen automatischen Speicherbereinigung führen, was zu einer höheren Latenz führt. Wenn Sie das Problem nicht auf ein Problem im Code zurückführen können, versuchen Sie, größere Instanzen mit mehr Arbeitsspeicher bereitzustellen.

Ressourcenleck

Wenn eine Instanz Ihrer Anwendung eine zunehmende Latenz aufweist, die mit dem Alter der Instanz korreliert, kann dies an einem Ressourcenleck liegen, das zu Leistungsproblemen führt. Die Latenz sinkt nach Abschluss einer Bereitstellung. Beispielsweise kann eine Datenstruktur, die aufgrund einer höheren CPU-Auslastung im Laufe der Zeit langsamer wird, dazu führen, dass jede CPU-gebundene Arbeitslast langsamer wird.

Codeoptimierung

Mit den folgenden Methoden können Sie den Code optimieren, um die Latenz in der App Engine zu reduzieren:

  • Offline-Arbeit: Mit Cloud Tasks können Sie verhindern, dass Nutzeranfragen die Anwendung blockieren, während auf den Abschluss von Arbeitslasten gewartet wird, z. B. beim Senden von E-Mails.

  • Asynchrone API-Aufrufe: Achten Sie darauf, dass Ihr Code nicht blockiert wird, bis ein API-Aufruf abgeschlossen ist.

  • Batch-API-Aufrufe: Die Batch-Version von API-Aufrufen ist normalerweise schneller als das Senden einzelner Aufrufe.

  • Datenmodelle denormalisieren: Reduzieren Sie die Latenz von Aufrufen an die Datenpersistenzebene, indem Sie Ihre Datenmodelle denormalisieren.

Anwendungsabhängigkeiten

Überwachen Sie die Abhängigkeiten Ihrer Anwendung, um zu erkennen, ob Latenzspitzen mit einem Abhängigkeitsfehler korrelieren.

Eine Änderung der Arbeitslast und ein Anstieg des Traffics können zu einer Erhöhung der Latenz einer Abhängigkeit führen.

Nicht skalierende Abhängigkeit

Wenn die Abhängigkeit Ihrer Anwendung nicht skaliert wird, wenn die Anzahl der App Engine-Instanzen vertikal skaliert wird, kann die Abhängigkeit überlastet werden, wenn der Traffic zunimmt. Ein Beispiel für eine Abhängigkeit, die möglicherweise nicht skaliert wird, ist eine SQL-Datenbank. Eine höhere Anzahl von Anwendungsinstanzen führt zu einer höheren Anzahl von Datenbankverbindungen, was zu kaskadierenden Fehlern führen kann, da der Start der Datenbank verhindert wird. So beheben Sie das Problem:

  1. Eine neue Standardversion bereitstellen, die keine Verbindung zur Datenbank herstellt.
  2. Vorherige Standardversion abschalten.
  3. Eine neue, nicht standardmäßige Version bereitstellen, die eine Verbindung zur Datenbank herstellt.
  4. Nach und nach Traffic zur neuen Version migrieren.

Als vorbeugende Maßnahme können Sie Ihre Anwendung so entwerfen, dass Anfragen an die Abhängigkeit mithilfe von adaptivem Throttling gesendet werden.

Ausfall der Caching-Ebene

Verwenden Sie mehrere Caching-Ebenen, z. B. Edge-Caching, Memcache und In-Instanz-Speicher, um Anfragen zu beschleunigen. Ein Fehler in einer dieser Caching-Ebenen kann zu einem plötzlichen Anstieg der Latenz führen. Ein Memcache-Flush kann beispielsweise dazu führen, dass mehr Anfragen an einen langsameren Datastore gesendet werden.