Gérer les risques liés au scaling

L'infrastructure de Google est conçue pour fonctionner de manière élastique à grande échelle : la plupart des couches peuvent s'adapter à une demande de trafic accrue, même à grande échelle. Ce fonctionnement est facilité par un schéma de conception fondamental qui est constitué de couches adaptatives, en d'autres termes, des composants d'infrastructure qui redistribuent la charge de manière dynamique en fonction des modèles de trafic. Cependant, cette adaptation prend du temps. Cloud Tasks permet de distribuer de très gros volumes de trafic et expose ainsi des risques de production dans les situations où le trafic peut augmenter plus rapidement que l'infrastructure ne peut s'adapter.

Présentation

Ce document répertorie les bonnes pratiques à adopter pour maintenir des performances élevées de Cloud Tasks dans des files d'attente à trafic élevé. Une file d'attente avec un nombre élevé de tâches par seconde est une file d'attente contenant au moins 500 tâches créées ou distribuées par seconde. Un groupe de files d'attente avec un nombre élevé de tâches par seconde est un ensemble contigu de files d'attente, par exemple [queue0001, queue0002, …, queue0099], pour lesquelles au moins 2 000 tâches ont été créées ou distribuées au total. L'historique des tâches par seconde d'une file d'attente ou d'un groupe de files d'attente peut être affiché à l'aide des métriques Stackdriver, de api/request_count pour les opérations "CreateTask" et de queue/task_attempt_count pour les tentatives de tâche. Les files d'attente et les groupes de files d'attente à trafic élevé sont sujets à deux grandes catégories d'échec :

La surcharge de la file d'attente se produit lorsque la création et la distribution des tâches dans une file d'attente individuelle ou un groupe de files d'attente augmentent plus rapidement que l'infrastructure de la file d'attente ne peut s'adapter. De même, la surcharge de la cible a lieu lorsque le taux auquel les tâches sont distribuées provoque des pics de trafic dans l'infrastructure cible en aval. Dans les deux cas, nous vous recommandons de suivre un schéma 500/50/5 : lorsque le scaling dépasse 500 tâches par seconde, augmentez le trafic jusqu'à 50 % toutes les cinq minutes. Ce document passe en revue différents scénarios pouvant introduire des risques liés au scaling et inclut des exemples sur la manière d'appliquer ce schéma.

Surcharge de la file d'attente

Les files d'attente ou les groupes de files d'attente peuvent être surchargés chaque fois que le trafic augmente soudainement. En conséquence, ces files d'attente peuvent rencontrer les problèmes suivants :

  • Augmentation de la latence liée à la création de tâches
  • Augmentation du taux d'erreur lié à la création de tâches
  • Réduction du taux de distribution

Pour éviter ces problèmes, nous vous recommandons d'établir des contrôles dans toutes les situations où le taux de création ou de distribution d'une file d'attente ou d'un groupe de files d'attente peut augmenter soudainement. Nous recommandons d'effectuer un maximum de 500 opérations par seconde sur une file d'attente ou un groupe de files d'attente à froid, puis d'augmenter le trafic de 50 % toutes les cinq minutes. En théorie, vous pouvez atteindre 740 000 opérations par seconde après 90 minutes en utilisant ce programme de montée en puissance. Ce scénario peut se produire dans un certain nombre de circonstances.

Exemples :

  • Lancement de nouvelles fonctionnalités qui dépendent fortement de Cloud Tasks
  • Déplacement du trafic entre les files d'attente
  • Rééquilibrage du trafic sur un nombre plus ou moins élevé de files d'attente
  • Exécution de tâches de traitement par lot qui injectent un grand nombre de tâches

Dans ces cas et dans d'autres, suivez le schéma 500/50/5.

Utiliser la répartition du trafic App Engine

Si les tâches sont créées par une application App Engine, vous pouvez utiliser la répartition du trafic App Engine (standard/flexible) pour atténuer les augmentations de trafic. En répartissant le trafic entre les versions (standard/flexible), les requêtes dont le taux doit être géré peuvent être accélérées au fil du temps pour protéger l'état de la file d'attente. À titre d'exemple, considérons le cas d'une augmentation du trafic vers un groupe de files d'attente nouvellement développé : [queue0000, queue0199] correspond à une séquence de files d'attente dont le nombre de tâches par seconde est élevé qui reçoit au maximum 100 000 créations de tâches par seconde.

[queue0200, queue0399] correspond à une séquence de nouvelles files d'attente. Une fois que tout le trafic a été déplacé, le nombre de files d'attente dans la séquence a doublé et la nouvelle plage de files d'attente reçoit 50 % du trafic total de la séquence.

Lors du déploiement de la version qui augmente le nombre de files d'attente, augmentez progressivement le trafic vers la nouvelle version, et donc les nouvelles files d'attente, à l'aide de la répartition du trafic :

  • Commencez par transférer 1 % du trafic vers la nouvelle version. Par exemple, 50 % de 1 % sur 100 000 tâches par seconde permettent d'obtenir 500 tâches par seconde sur l'ensemble de nouvelles files d'attente.
  • Toutes les cinq minutes, augmentez de 50 % le trafic envoyé à la nouvelle version, comme indiqué dans le tableau suivant :
Nombre de minutes depuis le début du déploiement % du trafic total transféré vers la nouvelle version % du trafic total transféré vers les nouvelles files d'attente % du trafic total transféré vers les anciennes files d'attente
0 1 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

Pics de trafic générés par les versions

Lors du lancement d'une version augmentant considérablement le trafic vers une file d'attente ou un groupe de files d'attente, le déploiement progressif est également un système important permettant d'atténuer les augmentations. Déployez progressivement les instances de sorte que le lancement initial ne dépasse pas 500 opérations au total dans les nouvelles files d'attente, en augmentant jusqu'à un maximum de 50 % toutes les cinq minutes.

Nouvelles files d'attente ou nouveaux groupes de files d'attente avec un nombre élevé de tâches par seconde

Les files d'attente nouvellement créées sont particulièrement vulnérables. Les groupes de files d'attente, par exemple [queue0000, queue0001, …, queue0199], sont aussi sensibles que les files d'attente simples lors des étapes initiales de déploiement. Pour ces files d'attente, le déploiement progressif est une stratégie importante. Lancez de nouveaux services ou des services mis à jour qui créent des files d'attente ou des groupes de files d'attente avec un nombre élevé de tâches par seconde par étapes : la charge initiale est inférieure à 500 tâches par seconde, et les augmentations de 50 % ou moins sont séparées d'au moins cinq minutes.

Groupes de files d'attente récemment développés

Lorsque vous augmentez la capacité totale d'un groupe de files d'attente, par exemple en développant [queue0000 – queue0199 vers queue0000 – queue0399], suivez le schéma 500/50/5. Il est important de noter que, pour les procédures de déploiement, les nouveaux groupes de files d'attente ne se comportent pas différemment des files d'attente individuelles. Appliquez le schéma 500/50/5 au nouveau groupe dans son ensemble, et pas seulement aux files d'attente individuelles du groupe. Pour les extensions de groupe de ces files d'attente, le déploiement progressif est aussi une stratégie importante. Si App Engine est la source du trafic, vous pouvez utiliser la répartition du trafic (consultez la section Pics de trafic générés par les versions). Lors de la migration du service pour ajouter des tâches au nombre accru de files d'attente, déployez progressivement les instances de sorte que le lancement initial ne dépasse pas 500 opérations au total dans les nouvelles files d'attente, en augmentant jusqu'à un maximum de 50 % toutes les cinq minutes.

Extension du groupe de files d'attente d'urgence

Dans certains cas, vous souhaiterez peut-être développer un groupe de files d'attente existant, par exemple lorsque des tâches doivent être ajoutées au groupe de files d'attente plus rapidement que le groupe ne peut les distribuer. Si les noms des nouvelles files d'attente sont répartis uniformément parmi les noms de file d'attente existants lorsqu'ils sont triés par ordre lexicographique, le trafic peut être immédiatement envoyé à ces files tant qu'il n'y a pas plus de 50 % de nouvelles files d'attente entrelacées et que le trafic vers chaque file d'attente est inférieur à 500 tâches par seconde. Cette méthode constitue une alternative à l'utilisation de la répartition du trafic et du déploiement progressif décrits dans les sections ci-dessus.

Ce type de dénomination entrelacée peut être obtenu en ajoutant un suffixe aux files d'attente se terminant par des nombres pairs. Par exemple, si vous avez 200 files d'attente existantes [queue0000 – queue0199] et que vous souhaitez créer 100 nouvelles files d'attente, choisissez [queue0000a, queue0002a, queue0004a, …, queue0198a] comme nouveaux noms de file d'attente au lieu de [queue0200 – queue0299].

Si vous avez besoin d'une augmentation supplémentaire, vous pouvez toujours entrelacer jusqu'à 50 % de files d'attente supplémentaires toutes les cinq minutes.

Mise de tâches à grande échelle/par lots en file d'attente

Lorsqu'un nombre important de tâches, par exemple des millions ou des milliards de tâches, doit être ajouté, un schéma à double injection peut être utile. Au lieu de créer des tâches à partir d'un seul travail, utilisez une file d'attente d'injecteur. Chaque tâche ajoutée à la file d'attente d'injecteur est ramifiée, et ajoute 100 tâches à la file d'attente ou au groupe de files d'attente souhaité. La file d'attente d'injecteur peut être accélérée dans le temps, par exemple à partir de cinq tâches par seconde, puis augmentée de 50 % toutes les cinq minutes.

Dénomination des tâches

Lorsque vous créez une tâche, Cloud Tasks lui attribue un nom unique par défaut. Vous pouvez attribuer votre propre nom à une tâche en utilisant le paramètre name. Cependant, cela introduit une surcharge de performances importante, entraînant des latences accrues et des taux d'erreur potentiellement plus élevés associés aux tâches nommées. Ces coûts peuvent être considérablement amplifiés si les tâches sont nommées de manière séquentielle, par exemple avec des horodatages. Par conséquent, si vous attribuez vos propres noms, nous vous recommandons d'utiliser un préfixe distribué de manière homogène pour les noms de tâches, tel qu'un hachage du contenu. Consultez la documentation pour plus de détails sur le nommage d'une tâche.

Surcharge de la cible

Cloud Tasks peut surcharger les autres services que vous utilisez, tels qu'App Engine, Datastore et votre utilisation du réseau, si les expéditions depuis une file d'attente augmentent considérablement sur une courte période. Si le nombre de tâches mises en attente augmente, le fait de relancer ces files d'attente peut potentiellement surcharger ces services. La méthode de protection recommandée utilise le même schéma 500/50/5 que celui suggéré pour la surcharge de la file d'attente : si une file d'attente distribue plus de 500 tâches par seconde, augmentez le trafic déclenché par une file d'attente jusqu'à un maximum de 50 % toutes les cinq minutes. Utilisez les métriques Stackdriver pour surveiller de manière proactive l'augmentation du trafic. Les alertes Stackdriver peuvent être utilisées pour détecter des situations potentiellement dangereuses.

Relancer ou réactiver les files d'attente avec un nombre élevé de tâches par seconde

Lorsqu'une file d'attente ou une série de files d'attente est relancée ou réactivée, les files d'attente reprennent les distributions. Si la file d'attente comporte de nombreuses tâches, le taux de distribution de la file nouvellement activée peut augmenter considérablement, passant de 0 tâche par seconde à la capacité totale de la file d'attente. Pour augmenter le trafic, la file d'attente décalée reprend ou contrôle les taux de distribution de la file d'attente à l'aide du champ maxDispatchesPerSecond de Cloud Tasks.

Planification des tâches groupées

Un grand nombre de tâches, dont la distribution est planifiée en même temps, peut également entraîner un risque de surcharge de la cible. Si vous devez démarrer un grand nombre de tâches en même temps, envisagez d'utiliser des contrôles de taux de file d'attente pour accroître le taux de distribution en augmentant progressivement ou explicitement la capacité cible à l'avance.

Augmentation de la distribution ramifiée

Lors de la mise à jour de services exécutés via Cloud Tasks, l'augmentation du nombre d'appels distants peut créer des risques pour la production. Par exemple, supposons que les tâches d'une file d'attente avec un nombre élevé de tâches par seconde appellent le gestionnaire /task-foo. Une nouvelle version peut augmenter considérablement le coût des appels /task-foo si, par exemple, cette nouvelle version ajoute plusieurs appels Datastore coûteux au gestionnaire. Le résultat net d'une telle version consiste en une augmentation considérable du trafic Datastore immédiatement liée aux changements du trafic utilisateur. Utilisez le déploiement progressif ou la répartition du trafic pour gérer une telle augmentation.

Tentatives

Le code peut effectuer de nouvelles tentatives en cas d'échec lors d'appels à l'API Cloud Tasks. Toutefois, lorsqu'une proportion importante des requêtes échoue avec des erreurs côté serveur, un nombre élevé de tentatives peut surcharger davantage les files d'attente et les ralentir. Par conséquent, nous recommandons de limiter le trafic sortant si le client détecte qu'une proportion importante des requêtes échoue avec des erreurs côté serveur, par exemple à l'aide de l'algorithme "Adaptive Throttling" décrit dans le chapitre Handling Overload du manuel Site Reliablity Engineering. Les bibliothèques clientes gRPC de Google mettent en œuvre une variante de cet algorithme.