Résoudre les problèmes de latence élevée dans les applications App Engine

Dans de nombreux cas, une latence élevée dans votre application entraînera à terme des erreurs de serveur 5xx. Étant donné que la cause première de l'erreur et des pics de latence peut être la même, appliquez les stratégies suivantes pour résoudre les problèmes de latence:

  1. Définir la portée du problème de latence
  2. Identifier la cause
  3. Résoudre les problèmes

Définir la portée du problème de latence

Définissez le champ d'application du problème en vous posant les questions suivantes:

  • Quelles applications, services et versions sont concernées par ce problème ?
  • Quels points de terminaison spécifiques du service sont affectés par ce problème ?
  • Ce problème a-t-il un impact sur tous les clients du monde entier ou sur un sous-ensemble de clients spécifique ?
  • Quelles sont les heures de début et de fin de l'incident ? Pensez à spécifier le fuseau horaire.
  • Quelles sont les erreurs spécifiques ?
  • Quel est le delta de latence observé, généralement spécifié sous la forme d'une augmentation à un centile spécifique ? Par exemple, la latence a augmenté de deux secondes au 90e centile.
  • Comment avez-vous mesuré la latence ? En particulier, l'avez-vous mesurée au niveau du client, ou est-elle visible dans Cloud Logging ou dans les données de latence de Cloud Monitoring fournies par l'infrastructure de diffusion App Engine ?
  • Quelles sont les dépendances de votre service et l'une d'entre elles a-t-elle subi des incidents ?
  • Avez-vous récemment apporté des modifications au code, à la configuration ou à la charge de travail qui ont déclenché ce problème ?

Un service peut disposer de sa propre surveillance et journalisation personnalisées, que vous pouvez utiliser pour affiner davantage la portée du problème. Définir l'étendue du problème vous orientera vers la cause probable et déterminera les prochaines étapes de dépannage.

Identifier la cause

Déterminez quel composant du chemin de requête est le plus susceptible de provoquer la latence ou les erreurs. Les principaux composants du chemin de requête sont les suivants:

Client --> Internet --> Google Front End (GFE) --> Infrastructure de diffusion App Engine --> Instance de service

Si les informations précédentes ne vous indiquent pas la source de la défaillance, appliquez les stratégies suivantes lorsque vous examinez l'état et les performances de votre instance de service:

  1. Surveillez les journaux de requêtes App Engine. Si vous constatez des erreurs de code d'état HTTP ou une latence élevée dans ces journaux, le problème se trouve probablement dans l'instance qui exécute votre service.

  2. Si le nombre d'instances de service n'a pas été adapté pour correspondre aux niveaux de trafic, vos instances peuvent être surchargées, ce qui entraîne une augmentation des erreurs et de la latence.

  3. Si vous constatez des erreurs ou une latence élevées dans Cloud Monitoring, le problème peut provenir de l'amont de l'équilibreur de charge, qui enregistre les métriques App Engine. Dans la plupart des cas, cela pointe vers un problème dans les instances de service.

  4. Si vous constatez une latence élevée ou des erreurs dans les métriques de surveillance, mais pas dans les journaux de requête, cela indique une défaillance d'équilibrage de charge ou une défaillance d'instance grave qui empêche l'équilibreur de charge d'acheminer les requêtes. Pour faire la distinction entre ces cas, consultez les journaux de requête avant le début de l'incident. Si les journaux de requêtes affichent une latence croissante avant l'échec, cela indique que l'échec des instances d'application a commencé avant que l'équilibreur de charge ne cesse d'y acheminer les requêtes.

Résoudre les problèmes

Cette section décrit les stratégies de dépannage pour les problèmes de latence élevés provenant des composants suivants du chemin de la requête:

  1. Internet
  2. Google Front End (GFE)
  3. Infrastructure de diffusion App Engine
  4. Instance d'application
  5. Dépendances de l'application

Internet

Votre application peut rencontrer des problèmes de latence en raison d'une mauvaise connectivité ou d'une bande passante réduite.

Connectivité Internet de mauvaise qualité

Pour déterminer si le problème provient d'une connexion Internet de mauvaise qualité, exécutez la commande suivante sur votre client:

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

La valeur de time_connect représente la latence de connexion du client au Google Front End le plus proche. Pour les connexions lentes, continuez à résoudre les problèmes à l'aide de traceroute pour déterminer quel saut sur le réseau est à l'origine du retard.

Exécutez des tests à partir de clients situés dans différents emplacements géographiques. App Engine achemine automatiquement les requêtes vers le centre de données Google le plus proche, qui varie en fonction de l'emplacement du client.

Faible bande passante

L'application peut répondre rapidement. Toutefois, les goulots d'étranglement du réseau empêchent l'infrastructure de diffusion App Engine d'envoyer rapidement des paquets sur le réseau, ce qui ralentit les réponses.

Google Front End (GFE)

Votre application peut rencontrer des problèmes de latence en raison d'un routage incorrect, de requêtes parallèles envoyées par des clients HTTP/2 ou de la fin des connexions SSL.

Mapper une adresse IP client à une région géographique

Google résout le nom d'hôte de l'application App Engine sur le GFE le plus proche du client, en fonction de l'adresse IP du client utilisée dans la résolution DNS. Si le résolveur DNS du client n'utilise pas le protocole EDNS0, Google risque de ne pas acheminer les requêtes client vers le GFE le plus proche.

Blocage en tête de ligne HTTP/2

Les clients HTTP/2 qui envoient plusieurs requêtes en parallèle peuvent constater une latence élevée en raison du blocage en tête de ligne au niveau du GFE. Pour résoudre ce problème, les clients doivent utiliser le protocole QUIC.

Terminaison SSL pour les domaines personnalisés

Le GFE peut mettre fin à la connexion SSL. Si vous utilisez un domaine personnalisé au lieu d'un domaine appspot.com, la terminaison SSL nécessite un saut supplémentaire. Cela peut augmenter la latence des applications exécutées dans certaines régions. Pour en savoir plus, consultez la section Mapper des domaines personnalisés.

Infrastructure de diffusion App Engine

Vous pouvez constater une latence élevée dans votre application en raison d'incidents à l'échelle du service ou d'une mise à l'échelle automatique.

Incidents à l'échelle du service

Google publie les détails d'un problème grave affectant l'ensemble des services dans le tableau de bord État des services. Toutefois, Google effectue des déploiements de manière progressive. Il est donc peu probable qu'un incident à l'échelle du service affecte toutes vos instances en même temps.

Autoscaling

Les scénarios d'autoscaling suivants peuvent entraîner une latence élevée ou des erreurs:

  • Effectuer un scaling à la hausse du trafic trop rapidement: il est possible que l'autoscaling App Engine ne puisse pas faire évoluer vos instances aussi rapidement que l'augmentation du trafic, ce qui entraîne une surcharge temporaire. En règle générale, la surcharge se produit lorsque le trafic est généré par un programme informatique plutôt que par des utilisateurs finaux. Pour résoudre ce problème, limitez le système qui génère le trafic.

  • Pics de trafic: les pics de trafic peuvent entraîner une latence élevée dans les cas où un service avec autoscaling doit évoluer plus rapidement que possible sans affecter la latence. Le trafic des utilisateurs finaux n'entraîne généralement pas de pics de trafic fréquents. Si vous constatez des pics de trafic, vous devez en rechercher la cause. Si un système de traitement par lot s'exécute à intervalles réguliers, vous pourrez peut-être lisser le trafic ou utiliser des paramètres de scaling différents.

  • Paramètres de l'autoscaler: l'autoscaler peut être configuré en fonction des caractéristiques de scaling de votre service. Les paramètres de scaling peuvent ne pas être optimaux dans les scénarios suivants:

    • Les paramètres de scaling de l'environnement standard App Engine peuvent provoquer une latence s'ils sont définis de manière trop agressive. Si vous voyez des réponses du serveur avec le code d'état 500 et le message "La requête a été interrompue après avoir attendu trop longtemps pour tenter de traiter votre requête" dans vos journaux, cela signifie que la requête a expiré dans la file d'attente en attendant une instance inactive.

    • Vous constaterez peut-être une augmentation du délai d'attente avec le scaling manuel, même lorsque vous avez provisionné suffisamment d'instances. Nous vous recommandons de ne pas utiliser le scaling manuel si votre application diffuse le trafic des utilisateurs finaux. Le scaling manuel est préférable pour les charges de travail telles que les files d'attente de tâches.

    • La mise à l'échelle de base minimise les coûts au détriment de la latence. Nous vous recommandons de ne pas utiliser l'autoscaling de base pour les services sensibles à la latence.

    • Le paramètre de scaling par défaut d'App Engine offre une latence optimale pour la plupart des services. Si vous voyez toujours des requêtes avec un délai d'attente élevé, spécifiez un nombre minimal d'instances. Si vous ajustez les paramètres de scaling de façon à réduire les coûts en minimisant les instances inactives, vous risquez de rencontrer des pics de latence en cas d'augmentation soudaine de la charge.

Nous vous recommandons de comparer les performances avec les paramètres de scaling par défaut, puis d'exécuter un nouveau benchmark après chaque modification apportée à ces paramètres.

Déploiements

Une latence élevée peu de temps après un déploiement indique que le scaling à la hausse que vous avez effectué avant de migrer le trafic n'est pas suffisant. Les instances plus récentes peuvent ne pas avoir vidé les caches locaux et peuvent donc être diffusées plus lentement que les instances plus anciennes.

Pour éviter les pics de latence, ne déployez pas un service App Engine avec le même nom de version qu'une version existante du service. Si vous réutilisez un nom de version existant, vous ne pourrez pas migrer progressivement le trafic vers la nouvelle version. Les requêtes peuvent être plus lentes, car App Engine redémarre chaque instance dans un court laps de temps. Vous devrez également effectuer un redéploiement si vous souhaitez revenir à la version précédente.

Instance d'application

Cette section décrit les stratégies courantes que vous pouvez appliquer à vos instances d'application et à votre code source pour optimiser les performances et réduire la latence.

Code d'application

Les problèmes liés au code d'application peuvent être difficiles à déboguer, en particulier s'ils sont intermittents ou non reproductibles.

Pour résoudre les problèmes, procédez comme suit:

  • Pour diagnostiquer vos problèmes, nous vous recommandons d'instrumenter votre application avec la journalisation, la surveillance et le traçage. Vous pouvez également utiliser Cloud Profiler.

  • Essayez de reproduire le problème dans un environnement de développement local, ce qui peut vous permettre d'exécuter des outils de débogage spécifiques à un langage qui ne peuvent pas être exécutés dans App Engine.

  • Pour mieux comprendre les échecs de votre application et identifier les goulots d'étranglement, testez la charge de votre application jusqu'à ce qu'elle échoue. Définissez un nombre maximal d'instances, puis augmentez progressivement la charge jusqu'à ce que l'application échoue.

  • Si le problème de latence est lié au déploiement d'une nouvelle version du code de votre application, effectuez un rollback pour déterminer si la nouvelle version est à l'origine de l'incident. Toutefois, si vous effectuez des déploiements en continu, leur fréquence empêche de déterminer si le déploiement a causé ou non l'incident en fonction de l'heure à laquelle il a eu lieu.

  • Votre application peut stocker les paramètres de configuration dans le datastore ou ailleurs. Créez une chronologie des modifications de configuration afin de déterminer si l'une de ces lignes correspond à l'apparition d'une latence élevée.

Modification de la charge de travail

Une modification de la charge de travail peut entraîner une latence élevée. Certaines métriques de surveillance qui indiquent des modifications de la charge de travail incluent qps, l'utilisation de l'API et la latence. Vérifiez également les modifications apportées à la taille des requêtes et des réponses.

Sollicitation de la mémoire

Si la surveillance montre un modèle d'utilisation de la mémoire en dents de scie ou une baisse d'utilisation de la mémoire liée aux déploiements, une fuite de mémoire peut être à l'origine de problèmes de performances. Une fuite de mémoire peut également entraîner une récupération fréquente de mémoire, ce qui entraîne une latence plus élevée. Si vous ne parvenez pas à identifier le problème dans le code, essayez de provisionner des instances plus volumineuses avec plus de mémoire.

Fuite de ressources

Si une instance de votre application présente une latence croissante liée à son ancienneté, il peut s'agir d'une fuite de ressources provoquant des problèmes de performances. La latence diminue une fois le déploiement terminé. Par exemple, une structure de données qui devient plus lente au fil du temps en raison d'une utilisation plus élevée du processeur peut ralentir la charge de travail liée au processeur.

Optimisation du code

Pour réduire la latence sur App Engine, optimisez le code à l'aide des méthodes suivantes:

  • Travailler hors connexion: utilisez Cloud Tasks pour empêcher les requêtes des utilisateurs de bloquer l'application en attendant l'exécution d'une tâche, comme l'envoi d'e-mails.

  • Appels d'API asynchrones: assurez-vous que votre code n'est pas bloqué en attendant la fin d'un appel d'API.

  • Appels d'API par lot: la version par lot des appels d'API est généralement plus rapide que l'envoi d'appels individuels.

  • Dénormaliser les modèles de données: réduisez la latence des appels passés sur la couche de persistance des données en dénormalisant vos modèles de données.

Dépendances de l'application

Surveillez les dépendances de votre application pour détecter si les pics de latence sont corrélés à l'échec d'une dépendance.

Une modification de la charge de travail et une augmentation du trafic peuvent entraîner une augmentation de la latence d'une dépendance.

Dépendance sans scaling

Si la dépendance de votre application n'évolue pas à mesure que le nombre d'instances App Engine augmente, elle peut être surchargée lorsque le trafic augmente. Une base de données SQL est un exemple de dépendance susceptible de ne pas évoluer. Un nombre plus élevé d'instances d'application entraîne une augmentation du nombre de connexions à la base de données, ce qui peut entraîner des défaillances en cascade en empêchant le démarrage de la base de données. Pour résoudre ce problème, procédez comme suit :

  1. Déployez une nouvelle version par défaut qui ne se connecte pas à la base de données.
  2. Fermez la version par défaut précédente.
  3. Déployez une nouvelle version autre que celle par défaut, qui se connecte à la base de données.
  4. Migrez progressivement le trafic vers la nouvelle version.

À titre préventif, concevez votre application de façon à supprimer les requêtes adressées à la dépendance à l'aide de la limitation adaptative.

Échec de la couche de mise en cache

Pour accélérer les requêtes, utilisez plusieurs couches de mise en cache, telles que la mise en cache de bord, Memcache et la mémoire dans l'instance. Une défaillance de l'une de ces couches de mise en cache peut entraîner une augmentation soudaine de la latence. Par exemple, un vidage Memcache peut entraîner l'envoi d'un plus grand nombre de requêtes à un datastore plus lent.